First commit for private source control. Older commits available on Github.
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3041a2296f3b1749b3ef18e695adee4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(HorizontalLineAttribute))]
|
||||
public class HorizontalLineDecoratorDrawer : DecoratorDrawer
|
||||
{
|
||||
public override float GetHeight()
|
||||
{
|
||||
HorizontalLineAttribute lineAttr = (HorizontalLineAttribute)attribute;
|
||||
return EditorGUIUtility.singleLineHeight + lineAttr.Height;
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position)
|
||||
{
|
||||
Rect rect = EditorGUI.IndentedRect(position);
|
||||
rect.y += EditorGUIUtility.singleLineHeight / 3.0f;
|
||||
HorizontalLineAttribute lineAttr = (HorizontalLineAttribute)attribute;
|
||||
NaughtyEditorGUI.HorizontalLine(rect, lineAttr.Height, lineAttr.Color.GetColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ec99f3a124f20e40b8f5edfeb1ecced
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/DecoratorDrawers/HorizontalLineDecoratorDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,59 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(InfoBoxAttribute))]
|
||||
public class InfoBoxDecoratorDrawer : DecoratorDrawer
|
||||
{
|
||||
public override float GetHeight()
|
||||
{
|
||||
return GetHelpBoxHeight();
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect rect)
|
||||
{
|
||||
InfoBoxAttribute infoBoxAttribute = (InfoBoxAttribute)attribute;
|
||||
|
||||
float indentLength = NaughtyEditorGUI.GetIndentLength(rect);
|
||||
Rect infoBoxRect = new Rect(
|
||||
rect.x + indentLength,
|
||||
rect.y,
|
||||
rect.width - indentLength,
|
||||
GetHelpBoxHeight());
|
||||
|
||||
DrawInfoBox(infoBoxRect, infoBoxAttribute.Text, infoBoxAttribute.Type);
|
||||
}
|
||||
|
||||
private float GetHelpBoxHeight()
|
||||
{
|
||||
InfoBoxAttribute infoBoxAttribute = (InfoBoxAttribute)attribute;
|
||||
float minHeight = EditorGUIUtility.singleLineHeight * 2.0f;
|
||||
float desiredHeight = GUI.skin.box.CalcHeight(new GUIContent(infoBoxAttribute.Text), EditorGUIUtility.currentViewWidth);
|
||||
float height = Mathf.Max(minHeight, desiredHeight);
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
private void DrawInfoBox(Rect rect, string infoText, EInfoBoxType infoBoxType)
|
||||
{
|
||||
MessageType messageType = MessageType.None;
|
||||
switch (infoBoxType)
|
||||
{
|
||||
case EInfoBoxType.Normal:
|
||||
messageType = MessageType.Info;
|
||||
break;
|
||||
|
||||
case EInfoBoxType.Warning:
|
||||
messageType = MessageType.Warning;
|
||||
break;
|
||||
|
||||
case EInfoBoxType.Error:
|
||||
messageType = MessageType.Error;
|
||||
break;
|
||||
}
|
||||
|
||||
NaughtyEditorGUI.HelpBox(rect, infoText, messageType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9c18b0e698717442b7631c5066d667f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/DecoratorDrawers/InfoBoxDecoratorDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "NaughtyAttributes.Editor",
|
||||
"references": [
|
||||
"NaughtyAttributes.Core"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f88fb04354076c646a4107a491394033
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/NaughtyAttributes.Editor.asmdef
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,221 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CanEditMultipleObjects]
|
||||
[CustomEditor(typeof(UnityEngine.Object), true)]
|
||||
public class NaughtyInspector : UnityEditor.Editor
|
||||
{
|
||||
private List<SerializedProperty> _serializedProperties = new List<SerializedProperty>();
|
||||
private IEnumerable<FieldInfo> _nonSerializedFields;
|
||||
private IEnumerable<PropertyInfo> _nativeProperties;
|
||||
private IEnumerable<MethodInfo> _methods;
|
||||
private Dictionary<string, SavedBool> _foldouts = new Dictionary<string, SavedBool>();
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
_nonSerializedFields = ReflectionUtility.GetAllFields(
|
||||
target, f => f.GetCustomAttributes(typeof(ShowNonSerializedFieldAttribute), true).Length > 0);
|
||||
|
||||
_nativeProperties = ReflectionUtility.GetAllProperties(
|
||||
target, p => p.GetCustomAttributes(typeof(ShowNativePropertyAttribute), true).Length > 0);
|
||||
|
||||
_methods = ReflectionUtility.GetAllMethods(
|
||||
target, m => m.GetCustomAttributes(typeof(ButtonAttribute), true).Length > 0);
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
ReorderableListPropertyDrawer.Instance.ClearCache();
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
GetSerializedProperties(ref _serializedProperties);
|
||||
|
||||
bool anyNaughtyAttribute = _serializedProperties.Any(p => PropertyUtility.GetAttribute<INaughtyAttribute>(p) != null);
|
||||
if (!anyNaughtyAttribute)
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawSerializedProperties();
|
||||
}
|
||||
|
||||
DrawNonSerializedFields();
|
||||
DrawNativeProperties();
|
||||
DrawButtons();
|
||||
}
|
||||
|
||||
protected void GetSerializedProperties(ref List<SerializedProperty> outSerializedProperties)
|
||||
{
|
||||
outSerializedProperties.Clear();
|
||||
using (var iterator = serializedObject.GetIterator())
|
||||
{
|
||||
if (iterator.NextVisible(true))
|
||||
{
|
||||
do
|
||||
{
|
||||
outSerializedProperties.Add(serializedObject.FindProperty(iterator.name));
|
||||
}
|
||||
while (iterator.NextVisible(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawSerializedProperties()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
// Draw non-grouped serialized properties
|
||||
foreach (var property in GetNonGroupedProperties(_serializedProperties))
|
||||
{
|
||||
if (property.name.Equals("m_Script", System.StringComparison.Ordinal))
|
||||
{
|
||||
using (new EditorGUI.DisabledScope(disabled: true))
|
||||
{
|
||||
EditorGUILayout.PropertyField(property);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NaughtyEditorGUI.PropertyField_Layout(property, includeChildren: true);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw grouped serialized properties
|
||||
foreach (var group in GetGroupedProperties(_serializedProperties))
|
||||
{
|
||||
IEnumerable<SerializedProperty> visibleProperties = group.Where(p => PropertyUtility.IsVisible(p));
|
||||
if (!visibleProperties.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
NaughtyEditorGUI.BeginBoxGroup_Layout(group.Key);
|
||||
foreach (var property in visibleProperties)
|
||||
{
|
||||
NaughtyEditorGUI.PropertyField_Layout(property, includeChildren: true);
|
||||
}
|
||||
|
||||
NaughtyEditorGUI.EndBoxGroup_Layout();
|
||||
}
|
||||
|
||||
// Draw foldout serialized properties
|
||||
foreach (var group in GetFoldoutProperties(_serializedProperties))
|
||||
{
|
||||
IEnumerable<SerializedProperty> visibleProperties = group.Where(p => PropertyUtility.IsVisible(p));
|
||||
if (!visibleProperties.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_foldouts.ContainsKey(group.Key))
|
||||
{
|
||||
_foldouts[group.Key] = new SavedBool($"{target.GetInstanceID()}.{group.Key}", false);
|
||||
}
|
||||
|
||||
_foldouts[group.Key].Value = EditorGUILayout.Foldout(_foldouts[group.Key].Value, group.Key, true);
|
||||
if (_foldouts[group.Key].Value)
|
||||
{
|
||||
foreach (var property in visibleProperties)
|
||||
{
|
||||
NaughtyEditorGUI.PropertyField_Layout(property, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
protected void DrawNonSerializedFields(bool drawHeader = false)
|
||||
{
|
||||
if (_nonSerializedFields.Any())
|
||||
{
|
||||
if (drawHeader)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Non-Serialized Fields", GetHeaderGUIStyle());
|
||||
NaughtyEditorGUI.HorizontalLine(
|
||||
EditorGUILayout.GetControlRect(false), HorizontalLineAttribute.DefaultHeight, HorizontalLineAttribute.DefaultColor.GetColor());
|
||||
}
|
||||
|
||||
foreach (var field in _nonSerializedFields)
|
||||
{
|
||||
NaughtyEditorGUI.NonSerializedField_Layout(serializedObject.targetObject, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawNativeProperties(bool drawHeader = false)
|
||||
{
|
||||
if (_nativeProperties.Any())
|
||||
{
|
||||
if (drawHeader)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Native Properties", GetHeaderGUIStyle());
|
||||
NaughtyEditorGUI.HorizontalLine(
|
||||
EditorGUILayout.GetControlRect(false), HorizontalLineAttribute.DefaultHeight, HorizontalLineAttribute.DefaultColor.GetColor());
|
||||
}
|
||||
|
||||
foreach (var property in _nativeProperties)
|
||||
{
|
||||
NaughtyEditorGUI.NativeProperty_Layout(serializedObject.targetObject, property);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawButtons(bool drawHeader = false)
|
||||
{
|
||||
if (_methods.Any())
|
||||
{
|
||||
if (drawHeader)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Buttons", GetHeaderGUIStyle());
|
||||
NaughtyEditorGUI.HorizontalLine(
|
||||
EditorGUILayout.GetControlRect(false), HorizontalLineAttribute.DefaultHeight, HorizontalLineAttribute.DefaultColor.GetColor());
|
||||
}
|
||||
|
||||
foreach (var method in _methods)
|
||||
{
|
||||
NaughtyEditorGUI.Button(serializedObject.targetObject, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<SerializedProperty> GetNonGroupedProperties(IEnumerable<SerializedProperty> properties)
|
||||
{
|
||||
return properties.Where(p => PropertyUtility.GetAttribute<IGroupAttribute>(p) == null);
|
||||
}
|
||||
|
||||
private static IEnumerable<IGrouping<string, SerializedProperty>> GetGroupedProperties(IEnumerable<SerializedProperty> properties)
|
||||
{
|
||||
return properties
|
||||
.Where(p => PropertyUtility.GetAttribute<BoxGroupAttribute>(p) != null)
|
||||
.GroupBy(p => PropertyUtility.GetAttribute<BoxGroupAttribute>(p).Name);
|
||||
}
|
||||
|
||||
private static IEnumerable<IGrouping<string, SerializedProperty>> GetFoldoutProperties(IEnumerable<SerializedProperty> properties)
|
||||
{
|
||||
return properties
|
||||
.Where(p => PropertyUtility.GetAttribute<FoldoutAttribute>(p) != null)
|
||||
.GroupBy(p => PropertyUtility.GetAttribute<FoldoutAttribute>(p).Name);
|
||||
}
|
||||
|
||||
private static GUIStyle GetHeaderGUIStyle()
|
||||
{
|
||||
GUIStyle style = new GUIStyle(EditorStyles.centeredGreyMiniLabel);
|
||||
style.fontStyle = FontStyle.Bold;
|
||||
style.alignment = TextAnchor.UpperCenter;
|
||||
|
||||
return style;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b9b53879f7c93b42835c3ad9e0d0a66
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/NaughtyInspector.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4327d74fca5deaa4c83c483fe468d274
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(AllowNestingAttribute))]
|
||||
public class AllowNestingPropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
EditorGUI.PropertyField(rect, property, label, true);
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3175e7041b8f4348bd652485a78e7b1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/AllowNestingPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,173 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Animations;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(AnimatorParamAttribute))]
|
||||
public class AnimatorParamPropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
private const string InvalidAnimatorControllerWarningMessage = "Target animator controller is null";
|
||||
private const string InvalidTypeWarningMessage = "{0} must be an int or a string";
|
||||
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
AnimatorParamAttribute animatorParamAttribute = PropertyUtility.GetAttribute<AnimatorParamAttribute>(property);
|
||||
bool validAnimatorController = GetAnimatorController(property, animatorParamAttribute.AnimatorName) != null;
|
||||
bool validPropertyType = property.propertyType == SerializedPropertyType.Integer || property.propertyType == SerializedPropertyType.String;
|
||||
|
||||
return (validAnimatorController && validPropertyType)
|
||||
? GetPropertyHeight(property)
|
||||
: GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
AnimatorParamAttribute animatorParamAttribute = PropertyUtility.GetAttribute<AnimatorParamAttribute>(property);
|
||||
|
||||
AnimatorController animatorController = GetAnimatorController(property, animatorParamAttribute.AnimatorName);
|
||||
if (animatorController == null)
|
||||
{
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, InvalidAnimatorControllerWarningMessage, MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
int parametersCount = animatorController.parameters.Length;
|
||||
List<AnimatorControllerParameter> animatorParameters = new List<AnimatorControllerParameter>(parametersCount);
|
||||
for (int i = 0; i < parametersCount; i++)
|
||||
{
|
||||
AnimatorControllerParameter parameter = animatorController.parameters[i];
|
||||
if (animatorParamAttribute.AnimatorParamType == null || parameter.type == animatorParamAttribute.AnimatorParamType)
|
||||
{
|
||||
animatorParameters.Add(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
switch (property.propertyType)
|
||||
{
|
||||
case SerializedPropertyType.Integer:
|
||||
DrawPropertyForInt(rect, property, label, animatorParameters);
|
||||
break;
|
||||
case SerializedPropertyType.String:
|
||||
DrawPropertyForString(rect, property, label, animatorParameters);
|
||||
break;
|
||||
default:
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, string.Format(InvalidTypeWarningMessage, property.name), MessageType.Warning);
|
||||
break;
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
private static void DrawPropertyForInt(Rect rect, SerializedProperty property, GUIContent label, List<AnimatorControllerParameter> animatorParameters)
|
||||
{
|
||||
int paramNameHash = property.intValue;
|
||||
int index = 0;
|
||||
|
||||
for (int i = 0; i < animatorParameters.Count; i++)
|
||||
{
|
||||
if (paramNameHash == animatorParameters[i].nameHash)
|
||||
{
|
||||
index = i + 1; // +1 because the first option is reserved for (None)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string[] displayOptions = GetDisplayOptions(animatorParameters);
|
||||
|
||||
int newIndex = EditorGUI.Popup(rect, label.text, index, displayOptions);
|
||||
int newValue = newIndex == 0 ? 0 : animatorParameters[newIndex - 1].nameHash;
|
||||
|
||||
if (property.intValue != newValue)
|
||||
{
|
||||
property.intValue = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawPropertyForString(Rect rect, SerializedProperty property, GUIContent label, List<AnimatorControllerParameter> animatorParameters)
|
||||
{
|
||||
string paramName = property.stringValue;
|
||||
int index = 0;
|
||||
|
||||
for (int i = 0; i < animatorParameters.Count; i++)
|
||||
{
|
||||
if (paramName.Equals(animatorParameters[i].name, System.StringComparison.Ordinal))
|
||||
{
|
||||
index = i + 1; // +1 because the first option is reserved for (None)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string[] displayOptions = GetDisplayOptions(animatorParameters);
|
||||
|
||||
int newIndex = EditorGUI.Popup(rect, label.text, index, displayOptions);
|
||||
string newValue = newIndex == 0 ? null : animatorParameters[newIndex - 1].name;
|
||||
|
||||
if (!property.stringValue.Equals(newValue, System.StringComparison.Ordinal))
|
||||
{
|
||||
property.stringValue = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
private static string[] GetDisplayOptions(List<AnimatorControllerParameter> animatorParams)
|
||||
{
|
||||
string[] displayOptions = new string[animatorParams.Count + 1];
|
||||
displayOptions[0] = "(None)";
|
||||
|
||||
for (int i = 0; i < animatorParams.Count; i++)
|
||||
{
|
||||
displayOptions[i + 1] = animatorParams[i].name;
|
||||
}
|
||||
|
||||
return displayOptions;
|
||||
}
|
||||
|
||||
private static AnimatorController GetAnimatorController(SerializedProperty property, string animatorName)
|
||||
{
|
||||
object target = PropertyUtility.GetTargetObjectWithProperty(property);
|
||||
|
||||
FieldInfo animatorFieldInfo = ReflectionUtility.GetField(target, animatorName);
|
||||
if (animatorFieldInfo != null &&
|
||||
animatorFieldInfo.FieldType == typeof(Animator))
|
||||
{
|
||||
Animator animator = animatorFieldInfo.GetValue(target) as Animator;
|
||||
if (animator != null)
|
||||
{
|
||||
AnimatorController animatorController = animator.runtimeAnimatorController as AnimatorController;
|
||||
return animatorController;
|
||||
}
|
||||
}
|
||||
|
||||
PropertyInfo animatorPropertyInfo = ReflectionUtility.GetProperty(target, animatorName);
|
||||
if (animatorPropertyInfo != null &&
|
||||
animatorPropertyInfo.PropertyType == typeof(Animator))
|
||||
{
|
||||
Animator animator = animatorPropertyInfo.GetValue(target) as Animator;
|
||||
if (animator != null)
|
||||
{
|
||||
AnimatorController animatorController = animator.runtimeAnimatorController as AnimatorController;
|
||||
return animatorController;
|
||||
}
|
||||
}
|
||||
|
||||
MethodInfo animatorGetterMethodInfo = ReflectionUtility.GetMethod(target, animatorName);
|
||||
if (animatorGetterMethodInfo != null &&
|
||||
animatorGetterMethodInfo.ReturnType == typeof(Animator) &&
|
||||
animatorGetterMethodInfo.GetParameters().Length == 0)
|
||||
{
|
||||
Animator animator = animatorGetterMethodInfo.Invoke(target, null) as Animator;
|
||||
if (animator != null)
|
||||
{
|
||||
AnimatorController animatorController = animator.runtimeAnimatorController as AnimatorController;
|
||||
return animatorController;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98ff8cb1bcefae740a68d9a5c5ee3563
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/AnimatorParamPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,47 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(CurveRangeAttribute))]
|
||||
public class CurveRangePropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
float propertyHeight = property.propertyType == SerializedPropertyType.AnimationCurve
|
||||
? GetPropertyHeight(property)
|
||||
: GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
|
||||
return propertyHeight;
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
// Check user error
|
||||
if (property.propertyType != SerializedPropertyType.AnimationCurve)
|
||||
{
|
||||
string message = string.Format("Field {0} is not an AnimationCurve", property.name);
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var curveRangeAttribute = (CurveRangeAttribute)attribute;
|
||||
var curveRanges = new Rect(
|
||||
curveRangeAttribute.Min.x,
|
||||
curveRangeAttribute.Min.y,
|
||||
curveRangeAttribute.Max.x - curveRangeAttribute.Min.x,
|
||||
curveRangeAttribute.Max.y - curveRangeAttribute.Min.y);
|
||||
|
||||
EditorGUI.CurveField(
|
||||
rect,
|
||||
property,
|
||||
curveRangeAttribute.Color == EColor.Clear ? Color.green : curveRangeAttribute.Color.GetColor(),
|
||||
curveRanges,
|
||||
label);
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 798b8c99fbc072a4b83ee387e472a2bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/CurveRangePropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,177 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(DropdownAttribute))]
|
||||
public class DropdownPropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
DropdownAttribute dropdownAttribute = (DropdownAttribute)attribute;
|
||||
object values = GetValues(property, dropdownAttribute.ValuesName);
|
||||
FieldInfo fieldInfo = ReflectionUtility.GetField(PropertyUtility.GetTargetObjectWithProperty(property), property.name);
|
||||
|
||||
float propertyHeight = AreValuesValid(values, fieldInfo)
|
||||
? GetPropertyHeight(property)
|
||||
: GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
|
||||
return propertyHeight;
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
DropdownAttribute dropdownAttribute = (DropdownAttribute)attribute;
|
||||
object target = PropertyUtility.GetTargetObjectWithProperty(property);
|
||||
|
||||
object valuesObject = GetValues(property, dropdownAttribute.ValuesName);
|
||||
FieldInfo dropdownField = ReflectionUtility.GetField(target, property.name);
|
||||
|
||||
if (AreValuesValid(valuesObject, dropdownField))
|
||||
{
|
||||
if (valuesObject is IList && dropdownField.FieldType == GetElementType(valuesObject))
|
||||
{
|
||||
// Selected value
|
||||
object selectedValue = dropdownField.GetValue(target);
|
||||
|
||||
// Values and display options
|
||||
IList valuesList = (IList)valuesObject;
|
||||
object[] values = new object[valuesList.Count];
|
||||
string[] displayOptions = new string[valuesList.Count];
|
||||
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
{
|
||||
object value = valuesList[i];
|
||||
values[i] = value;
|
||||
displayOptions[i] = value == null ? "<null>" : value.ToString();
|
||||
}
|
||||
|
||||
// Selected value index
|
||||
int selectedValueIndex = Array.IndexOf(values, selectedValue);
|
||||
if (selectedValueIndex < 0)
|
||||
{
|
||||
selectedValueIndex = 0;
|
||||
}
|
||||
|
||||
NaughtyEditorGUI.Dropdown(
|
||||
rect, property.serializedObject, target, dropdownField, label.text, selectedValueIndex, values, displayOptions);
|
||||
}
|
||||
else if (valuesObject is IDropdownList)
|
||||
{
|
||||
// Current value
|
||||
object selectedValue = dropdownField.GetValue(target);
|
||||
|
||||
// Current value index, values and display options
|
||||
int index = -1;
|
||||
int selectedValueIndex = -1;
|
||||
List<object> values = new List<object>();
|
||||
List<string> displayOptions = new List<string>();
|
||||
IDropdownList dropdown = (IDropdownList)valuesObject;
|
||||
|
||||
using (IEnumerator<KeyValuePair<string, object>> dropdownEnumerator = dropdown.GetEnumerator())
|
||||
{
|
||||
while (dropdownEnumerator.MoveNext())
|
||||
{
|
||||
index++;
|
||||
|
||||
KeyValuePair<string, object> current = dropdownEnumerator.Current;
|
||||
if (current.Value?.Equals(selectedValue) == true)
|
||||
{
|
||||
selectedValueIndex = index;
|
||||
}
|
||||
|
||||
values.Add(current.Value);
|
||||
|
||||
if (current.Key == null)
|
||||
{
|
||||
displayOptions.Add("<null>");
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(current.Key))
|
||||
{
|
||||
displayOptions.Add("<empty>");
|
||||
}
|
||||
else
|
||||
{
|
||||
displayOptions.Add(current.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedValueIndex < 0)
|
||||
{
|
||||
selectedValueIndex = 0;
|
||||
}
|
||||
|
||||
NaughtyEditorGUI.Dropdown(
|
||||
rect, property.serializedObject, target, dropdownField, label.text, selectedValueIndex, values.ToArray(), displayOptions.ToArray());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = string.Format("Invalid values with name '{0}' provided to '{1}'. Either the values name is incorrect or the types of the target field and the values field/property/method don't match",
|
||||
dropdownAttribute.ValuesName, dropdownAttribute.GetType().Name);
|
||||
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
private object GetValues(SerializedProperty property, string valuesName)
|
||||
{
|
||||
object target = PropertyUtility.GetTargetObjectWithProperty(property);
|
||||
|
||||
FieldInfo valuesFieldInfo = ReflectionUtility.GetField(target, valuesName);
|
||||
if (valuesFieldInfo != null)
|
||||
{
|
||||
return valuesFieldInfo.GetValue(target);
|
||||
}
|
||||
|
||||
PropertyInfo valuesPropertyInfo = ReflectionUtility.GetProperty(target, valuesName);
|
||||
if (valuesPropertyInfo != null)
|
||||
{
|
||||
return valuesPropertyInfo.GetValue(target);
|
||||
}
|
||||
|
||||
MethodInfo methodValuesInfo = ReflectionUtility.GetMethod(target, valuesName);
|
||||
if (methodValuesInfo != null &&
|
||||
methodValuesInfo.ReturnType != typeof(void) &&
|
||||
methodValuesInfo.GetParameters().Length == 0)
|
||||
{
|
||||
return methodValuesInfo.Invoke(target, null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool AreValuesValid(object values, FieldInfo dropdownField)
|
||||
{
|
||||
if (values == null || dropdownField == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((values is IList && dropdownField.FieldType == GetElementType(values)) ||
|
||||
(values is IDropdownList))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Type GetElementType(object values)
|
||||
{
|
||||
Type valuesType = values.GetType();
|
||||
Type elementType = ReflectionUtility.GetListElementType(valuesType);
|
||||
|
||||
return elementType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd080b36769bcd94d909fc0431cf25e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/DropdownPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,38 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(EnumFlagsAttribute))]
|
||||
public class EnumFlagsPropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
Enum targetEnum = PropertyUtility.GetTargetObjectOfProperty(property) as Enum;
|
||||
|
||||
return (targetEnum != null)
|
||||
? GetPropertyHeight(property)
|
||||
: GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
Enum targetEnum = PropertyUtility.GetTargetObjectOfProperty(property) as Enum;
|
||||
if (targetEnum != null)
|
||||
{
|
||||
Enum enumNew = EditorGUI.EnumFlagsField(rect, label.text, targetEnum);
|
||||
property.intValue = (int)Convert.ChangeType(enumNew, targetEnum.GetType());
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = attribute.GetType().Name + " can be used only on enums";
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b750e1461c1126d4399459b90b31e75e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/EnumFlagsPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,195 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(ExpandableAttribute))]
|
||||
public class ExpandablePropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (property.objectReferenceValue == null)
|
||||
{
|
||||
return GetPropertyHeight(property);
|
||||
}
|
||||
|
||||
System.Type propertyType = PropertyUtility.GetPropertyType(property);
|
||||
if (typeof(ScriptableObject).IsAssignableFrom(propertyType))
|
||||
{
|
||||
ScriptableObject scriptableObject = property.objectReferenceValue as ScriptableObject;
|
||||
if (scriptableObject == null)
|
||||
{
|
||||
return GetPropertyHeight(property);
|
||||
}
|
||||
|
||||
if (property.isExpanded)
|
||||
{
|
||||
using (SerializedObject serializedObject = new SerializedObject(scriptableObject))
|
||||
{
|
||||
float totalHeight = EditorGUIUtility.singleLineHeight;
|
||||
|
||||
using (var iterator = serializedObject.GetIterator())
|
||||
{
|
||||
if (iterator.NextVisible(true))
|
||||
{
|
||||
do
|
||||
{
|
||||
SerializedProperty childProperty = serializedObject.FindProperty(iterator.name);
|
||||
if (childProperty.name.Equals("m_Script", System.StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool visible = PropertyUtility.IsVisible(childProperty);
|
||||
if (!visible)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float height = GetPropertyHeight(childProperty);
|
||||
totalHeight += height;
|
||||
}
|
||||
while (iterator.NextVisible(false));
|
||||
}
|
||||
}
|
||||
|
||||
totalHeight += EditorGUIUtility.standardVerticalSpacing;
|
||||
return totalHeight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetPropertyHeight(property);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
if (property.objectReferenceValue == null)
|
||||
{
|
||||
EditorGUI.PropertyField(rect, property, label, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Type propertyType = PropertyUtility.GetPropertyType(property);
|
||||
if (typeof(ScriptableObject).IsAssignableFrom(propertyType))
|
||||
{
|
||||
ScriptableObject scriptableObject = property.objectReferenceValue as ScriptableObject;
|
||||
if (scriptableObject == null)
|
||||
{
|
||||
EditorGUI.PropertyField(rect, property, label, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw a foldout
|
||||
Rect foldoutRect = new Rect()
|
||||
{
|
||||
x = rect.x,
|
||||
y = rect.y,
|
||||
width = EditorGUIUtility.labelWidth,
|
||||
height = EditorGUIUtility.singleLineHeight
|
||||
};
|
||||
|
||||
property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, label, toggleOnLabelClick: true);
|
||||
|
||||
// Draw the scriptable object field
|
||||
Rect propertyRect = new Rect()
|
||||
{
|
||||
x = rect.x,
|
||||
y = rect.y,
|
||||
width = rect.width,
|
||||
height = EditorGUIUtility.singleLineHeight
|
||||
};
|
||||
|
||||
EditorGUI.PropertyField(propertyRect, property, label, false);
|
||||
|
||||
// Draw the child properties
|
||||
if (property.isExpanded)
|
||||
{
|
||||
DrawChildProperties(rect, property);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = $"{typeof(ExpandableAttribute).Name} can only be used on scriptable objects";
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
private void DrawChildProperties(Rect rect, SerializedProperty property)
|
||||
{
|
||||
ScriptableObject scriptableObject = property.objectReferenceValue as ScriptableObject;
|
||||
if (scriptableObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Rect boxRect = new Rect()
|
||||
{
|
||||
x = 0.0f,
|
||||
y = rect.y + EditorGUIUtility.singleLineHeight,
|
||||
width = rect.width * 2.0f,
|
||||
height = rect.height - EditorGUIUtility.singleLineHeight
|
||||
};
|
||||
|
||||
GUI.Box(boxRect, GUIContent.none);
|
||||
|
||||
using (new EditorGUI.IndentLevelScope())
|
||||
{
|
||||
SerializedObject serializedObject = new SerializedObject(scriptableObject);
|
||||
serializedObject.Update();
|
||||
|
||||
using (var iterator = serializedObject.GetIterator())
|
||||
{
|
||||
float yOffset = EditorGUIUtility.singleLineHeight;
|
||||
|
||||
if (iterator.NextVisible(true))
|
||||
{
|
||||
do
|
||||
{
|
||||
SerializedProperty childProperty = serializedObject.FindProperty(iterator.name);
|
||||
if (childProperty.name.Equals("m_Script", System.StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool visible = PropertyUtility.IsVisible(childProperty);
|
||||
if (!visible)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float childHeight = GetPropertyHeight(childProperty);
|
||||
Rect childRect = new Rect()
|
||||
{
|
||||
x = rect.x,
|
||||
y = rect.y + yOffset,
|
||||
width = rect.width,
|
||||
height = childHeight
|
||||
};
|
||||
|
||||
NaughtyEditorGUI.PropertyField(childRect, childProperty, true);
|
||||
|
||||
yOffset += childHeight;
|
||||
}
|
||||
while (iterator.NextVisible(false));
|
||||
}
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d1ddb7194615bdc4e8b2088c8d165d8b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ExpandablePropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,77 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(InputAxisAttribute))]
|
||||
public class InputAxisPropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
private static readonly string AssetPath = Path.Combine("ProjectSettings", "InputManager.asset");
|
||||
private const string AxesPropertyPath = "m_Axes";
|
||||
private const string NamePropertyPath = "m_Name";
|
||||
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return (property.propertyType == SerializedPropertyType.String)
|
||||
? GetPropertyHeight(property)
|
||||
: GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.String)
|
||||
{
|
||||
var inputManagerAsset = AssetDatabase.LoadAssetAtPath(AssetPath, typeof(object));
|
||||
var inputManager = new SerializedObject(inputManagerAsset);
|
||||
|
||||
var axesProperty = inputManager.FindProperty(AxesPropertyPath);
|
||||
var axesSet = new HashSet<string>();
|
||||
axesSet.Add("(None)");
|
||||
|
||||
for (var i = 0; i < axesProperty.arraySize; i++)
|
||||
{
|
||||
var axis = axesProperty.GetArrayElementAtIndex(i).FindPropertyRelative(NamePropertyPath).stringValue;
|
||||
axesSet.Add(axis);
|
||||
}
|
||||
|
||||
var axes = axesSet.ToArray();
|
||||
|
||||
string propertyString = property.stringValue;
|
||||
int index = 0;
|
||||
// check if there is an entry that matches the entry and get the index
|
||||
// we skip index 0 as that is a special custom case
|
||||
for (int i = 1; i < axes.Length; i++)
|
||||
{
|
||||
if (axes[i].Equals(propertyString, System.StringComparison.Ordinal))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the popup box with the current selected index
|
||||
int newIndex = EditorGUI.Popup(rect, label.text, index, axes);
|
||||
|
||||
// Adjust the actual string value of the property based on the selection
|
||||
string newValue = newIndex > 0 ? axes[newIndex] : string.Empty;
|
||||
|
||||
if (!property.stringValue.Equals(newValue, System.StringComparison.Ordinal))
|
||||
{
|
||||
property.stringValue = newValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = string.Format("{0} supports only string fields", typeof(InputAxisAttribute).Name);
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0de9d3dfe2d466a458be838edf361645
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/InputAxisPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,88 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(LayerAttribute))]
|
||||
public class LayerPropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
private const string TypeWarningMessage = "{0} must be an int or a string";
|
||||
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
bool validPropertyType = property.propertyType == SerializedPropertyType.String || property.propertyType == SerializedPropertyType.Integer;
|
||||
|
||||
return validPropertyType
|
||||
? GetPropertyHeight(property)
|
||||
: GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
switch (property.propertyType)
|
||||
{
|
||||
case SerializedPropertyType.String:
|
||||
DrawPropertyForString(rect, property, label, GetLayers());
|
||||
break;
|
||||
case SerializedPropertyType.Integer:
|
||||
DrawPropertyForInt(rect, property, label, GetLayers());
|
||||
break;
|
||||
default:
|
||||
string message = string.Format(TypeWarningMessage, property.name);
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
break;
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
private string[] GetLayers()
|
||||
{
|
||||
return UnityEditorInternal.InternalEditorUtility.layers;
|
||||
}
|
||||
|
||||
private static void DrawPropertyForString(Rect rect, SerializedProperty property, GUIContent label, string[] layers)
|
||||
{
|
||||
int index = IndexOf(layers, property.stringValue);
|
||||
int newIndex = EditorGUI.Popup(rect, label.text, index, layers);
|
||||
string newLayer = layers[newIndex];
|
||||
|
||||
if (!property.stringValue.Equals(newLayer, StringComparison.Ordinal))
|
||||
{
|
||||
property.stringValue = layers[newIndex];
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawPropertyForInt(Rect rect, SerializedProperty property, GUIContent label, string[] layers)
|
||||
{
|
||||
int index = 0;
|
||||
string layerName = LayerMask.LayerToName(property.intValue);
|
||||
for (int i = 0; i < layers.Length; i++)
|
||||
{
|
||||
if (layerName.Equals(layers[i], StringComparison.Ordinal))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int newIndex = EditorGUI.Popup(rect, label.text, index, layers);
|
||||
string newLayerName = layers[newIndex];
|
||||
int newLayerNumber = LayerMask.NameToLayer(newLayerName);
|
||||
|
||||
if (property.intValue != newLayerNumber)
|
||||
{
|
||||
property.intValue = newLayerNumber;
|
||||
}
|
||||
}
|
||||
|
||||
private static int IndexOf(string[] layers, string layer)
|
||||
{
|
||||
var index = Array.IndexOf(layers, layer);
|
||||
return Mathf.Clamp(index, 0, layers.Length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7278ba0893ab7d940b5f944e5b1cf1a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/LayerPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,108 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(MinMaxSliderAttribute))]
|
||||
public class MinMaxSliderPropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return (property.propertyType == SerializedPropertyType.Vector2 || property.propertyType == SerializedPropertyType.Vector2Int)
|
||||
? GetPropertyHeight(property)
|
||||
: GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
MinMaxSliderAttribute minMaxSliderAttribute = (MinMaxSliderAttribute)attribute;
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.Vector2 || property.propertyType == SerializedPropertyType.Vector2Int)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
float indentLength = NaughtyEditorGUI.GetIndentLength(rect);
|
||||
float labelWidth = EditorGUIUtility.labelWidth + NaughtyEditorGUI.HorizontalSpacing;
|
||||
float floatFieldWidth = EditorGUIUtility.fieldWidth;
|
||||
float sliderWidth = rect.width - labelWidth - 2.0f * floatFieldWidth;
|
||||
float sliderPadding = 5.0f;
|
||||
|
||||
Rect labelRect = new Rect(
|
||||
rect.x,
|
||||
rect.y,
|
||||
labelWidth,
|
||||
rect.height);
|
||||
|
||||
Rect sliderRect = new Rect(
|
||||
rect.x + labelWidth + floatFieldWidth + sliderPadding - indentLength,
|
||||
rect.y,
|
||||
sliderWidth - 2.0f * sliderPadding + indentLength,
|
||||
rect.height);
|
||||
|
||||
Rect minFloatFieldRect = new Rect(
|
||||
rect.x + labelWidth - indentLength,
|
||||
rect.y,
|
||||
floatFieldWidth + indentLength,
|
||||
rect.height);
|
||||
|
||||
Rect maxFloatFieldRect = new Rect(
|
||||
rect.x + labelWidth + floatFieldWidth + sliderWidth - indentLength,
|
||||
rect.y,
|
||||
floatFieldWidth + indentLength,
|
||||
rect.height);
|
||||
|
||||
// Draw the label
|
||||
EditorGUI.LabelField(labelRect, label.text);
|
||||
|
||||
// Draw the slider
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.Vector2)
|
||||
{
|
||||
Vector2 sliderValue = property.vector2Value;
|
||||
EditorGUI.MinMaxSlider(sliderRect, ref sliderValue.x, ref sliderValue.y, minMaxSliderAttribute.MinValue, minMaxSliderAttribute.MaxValue);
|
||||
|
||||
sliderValue.x = EditorGUI.FloatField(minFloatFieldRect, sliderValue.x);
|
||||
sliderValue.x = Mathf.Clamp(sliderValue.x, minMaxSliderAttribute.MinValue, Mathf.Min(minMaxSliderAttribute.MaxValue, sliderValue.y));
|
||||
|
||||
sliderValue.y = EditorGUI.FloatField(maxFloatFieldRect, sliderValue.y);
|
||||
sliderValue.y = Mathf.Clamp(sliderValue.y, Mathf.Max(minMaxSliderAttribute.MinValue, sliderValue.x), minMaxSliderAttribute.MaxValue);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
property.vector2Value = sliderValue;
|
||||
}
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector2Int)
|
||||
{
|
||||
Vector2Int sliderValue = property.vector2IntValue;
|
||||
float xValue = sliderValue.x;
|
||||
float yValue = sliderValue.y;
|
||||
EditorGUI.MinMaxSlider(sliderRect, ref xValue, ref yValue, minMaxSliderAttribute.MinValue, minMaxSliderAttribute.MaxValue);
|
||||
|
||||
sliderValue.x = EditorGUI.IntField(minFloatFieldRect, (int)xValue);
|
||||
sliderValue.x = (int)Mathf.Clamp(sliderValue.x, minMaxSliderAttribute.MinValue, Mathf.Min(minMaxSliderAttribute.MaxValue, sliderValue.y));
|
||||
|
||||
sliderValue.y = EditorGUI.IntField(maxFloatFieldRect, (int)yValue);
|
||||
sliderValue.y = (int)Mathf.Clamp(sliderValue.y, Mathf.Max(minMaxSliderAttribute.MinValue, sliderValue.x), minMaxSliderAttribute.MaxValue);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
property.vector2IntValue = sliderValue;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = minMaxSliderAttribute.GetType().Name + " can be used only on Vector2 or Vector2Int fields";
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 27011af81554b5b4489b155f09275475
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/MinMaxSliderPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,154 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Reflection;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(ProgressBarAttribute))]
|
||||
public class ProgressBarPropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
ProgressBarAttribute progressBarAttribute = PropertyUtility.GetAttribute<ProgressBarAttribute>(property);
|
||||
var maxValue = GetMaxValue(property, progressBarAttribute);
|
||||
|
||||
return IsNumber(property) && IsNumber(maxValue)
|
||||
? GetPropertyHeight(property)
|
||||
: GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
if (!IsNumber(property))
|
||||
{
|
||||
string message = string.Format("Field {0} is not a number", property.name);
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
ProgressBarAttribute progressBarAttribute = PropertyUtility.GetAttribute<ProgressBarAttribute>(property);
|
||||
var value = property.propertyType == SerializedPropertyType.Integer ? property.intValue : property.floatValue;
|
||||
var valueFormatted = property.propertyType == SerializedPropertyType.Integer ? value.ToString() : string.Format("{0:0.00}", value);
|
||||
var maxValue = GetMaxValue(property, progressBarAttribute);
|
||||
|
||||
if (maxValue != null && IsNumber(maxValue))
|
||||
{
|
||||
var fillPercentage = value / CastToFloat(maxValue);
|
||||
var barLabel = (!string.IsNullOrEmpty(progressBarAttribute.Name) ? "[" + progressBarAttribute.Name + "] " : "") + valueFormatted + "/" + maxValue;
|
||||
var barColor = progressBarAttribute.Color.GetColor();
|
||||
var labelColor = Color.white;
|
||||
|
||||
var indentLength = NaughtyEditorGUI.GetIndentLength(rect);
|
||||
Rect barRect = new Rect()
|
||||
{
|
||||
x = rect.x + indentLength,
|
||||
y = rect.y,
|
||||
width = rect.width - indentLength,
|
||||
height = EditorGUIUtility.singleLineHeight
|
||||
};
|
||||
|
||||
DrawBar(barRect, Mathf.Clamp01(fillPercentage), barLabel, barColor, labelColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = string.Format(
|
||||
"The provided dynamic max value for the progress bar is not correct. Please check if the '{0}' is correct, or the return type is float/int",
|
||||
nameof(progressBarAttribute.MaxValueName));
|
||||
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
private object GetMaxValue(SerializedProperty property, ProgressBarAttribute progressBarAttribute)
|
||||
{
|
||||
if (string.IsNullOrEmpty(progressBarAttribute.MaxValueName))
|
||||
{
|
||||
return progressBarAttribute.MaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
object target = PropertyUtility.GetTargetObjectWithProperty(property);
|
||||
|
||||
FieldInfo valuesFieldInfo = ReflectionUtility.GetField(target, progressBarAttribute.MaxValueName);
|
||||
if (valuesFieldInfo != null)
|
||||
{
|
||||
return valuesFieldInfo.GetValue(target);
|
||||
}
|
||||
|
||||
PropertyInfo valuesPropertyInfo = ReflectionUtility.GetProperty(target, progressBarAttribute.MaxValueName);
|
||||
if (valuesPropertyInfo != null)
|
||||
{
|
||||
return valuesPropertyInfo.GetValue(target);
|
||||
}
|
||||
|
||||
MethodInfo methodValuesInfo = ReflectionUtility.GetMethod(target, progressBarAttribute.MaxValueName);
|
||||
if (methodValuesInfo != null &&
|
||||
(methodValuesInfo.ReturnType == typeof(float) || methodValuesInfo.ReturnType == typeof(int)) &&
|
||||
methodValuesInfo.GetParameters().Length == 0)
|
||||
{
|
||||
return methodValuesInfo.Invoke(target, null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBar(Rect rect, float fillPercent, string label, Color barColor, Color labelColor)
|
||||
{
|
||||
if (Event.current.type != EventType.Repaint)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var fillRect = new Rect(rect.x, rect.y, rect.width * fillPercent, rect.height);
|
||||
|
||||
EditorGUI.DrawRect(rect, new Color(0.13f, 0.13f, 0.13f));
|
||||
EditorGUI.DrawRect(fillRect, barColor);
|
||||
|
||||
// set alignment and cache the default
|
||||
var align = GUI.skin.label.alignment;
|
||||
GUI.skin.label.alignment = TextAnchor.UpperCenter;
|
||||
|
||||
// set the color and cache the default
|
||||
var c = GUI.contentColor;
|
||||
GUI.contentColor = labelColor;
|
||||
|
||||
// calculate the position
|
||||
var labelRect = new Rect(rect.x, rect.y - 2, rect.width, rect.height);
|
||||
|
||||
// draw~
|
||||
EditorGUI.DropShadowLabel(labelRect, label);
|
||||
|
||||
// reset color and alignment
|
||||
GUI.contentColor = c;
|
||||
GUI.skin.label.alignment = align;
|
||||
}
|
||||
|
||||
private bool IsNumber(SerializedProperty property)
|
||||
{
|
||||
bool isNumber = property.propertyType == SerializedPropertyType.Float || property.propertyType == SerializedPropertyType.Integer;
|
||||
return isNumber;
|
||||
}
|
||||
|
||||
private bool IsNumber(object obj)
|
||||
{
|
||||
return (obj is float) || (obj is int);
|
||||
}
|
||||
|
||||
private float CastToFloat(object obj)
|
||||
{
|
||||
if (obj is int)
|
||||
{
|
||||
return (int)obj;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (float)obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0bcbc424b10864b4eb6e3bcfb276cdf9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ProgressBarPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,94 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public abstract class PropertyDrawerBase : PropertyDrawer
|
||||
{
|
||||
public sealed override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
// Check if visible
|
||||
bool visible = PropertyUtility.IsVisible(property);
|
||||
if (!visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate
|
||||
ValidatorAttribute[] validatorAttributes = PropertyUtility.GetAttributes<ValidatorAttribute>(property);
|
||||
foreach (var validatorAttribute in validatorAttributes)
|
||||
{
|
||||
validatorAttribute.GetValidator().ValidateProperty(property);
|
||||
}
|
||||
|
||||
// Check if enabled and draw
|
||||
EditorGUI.BeginChangeCheck();
|
||||
bool enabled = PropertyUtility.IsEnabled(property);
|
||||
|
||||
using (new EditorGUI.DisabledScope(disabled: !enabled))
|
||||
{
|
||||
OnGUI_Internal(rect, property, PropertyUtility.GetLabel(property));
|
||||
}
|
||||
|
||||
// Call OnValueChanged callbacks
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
PropertyUtility.CallOnValueChangedCallbacks(property);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label);
|
||||
|
||||
sealed override public float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
bool visible = PropertyUtility.IsVisible(property);
|
||||
if (!visible)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return GetPropertyHeight_Internal(property, label);
|
||||
}
|
||||
|
||||
protected virtual float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return EditorGUI.GetPropertyHeight(property, includeChildren: true);
|
||||
}
|
||||
|
||||
protected float GetPropertyHeight(SerializedProperty property)
|
||||
{
|
||||
SpecialCaseDrawerAttribute specialCaseAttribute = PropertyUtility.GetAttribute<SpecialCaseDrawerAttribute>(property);
|
||||
if (specialCaseAttribute != null)
|
||||
{
|
||||
return specialCaseAttribute.GetDrawer().GetPropertyHeight(property);
|
||||
}
|
||||
|
||||
return EditorGUI.GetPropertyHeight(property, includeChildren: true);
|
||||
}
|
||||
|
||||
public virtual float GetHelpBoxHeight()
|
||||
{
|
||||
return EditorGUIUtility.singleLineHeight * 2.0f;
|
||||
}
|
||||
|
||||
public void DrawDefaultPropertyAndHelpBox(Rect rect, SerializedProperty property, string message, MessageType messageType)
|
||||
{
|
||||
float indentLength = NaughtyEditorGUI.GetIndentLength(rect);
|
||||
Rect helpBoxRect = new Rect(
|
||||
rect.x + indentLength,
|
||||
rect.y,
|
||||
rect.width - indentLength,
|
||||
GetHelpBoxHeight());
|
||||
|
||||
NaughtyEditorGUI.HelpBox(helpBoxRect, message, MessageType.Warning, context: property.serializedObject.targetObject);
|
||||
|
||||
Rect propertyRect = new Rect(
|
||||
rect.x,
|
||||
rect.y + GetHelpBoxHeight(),
|
||||
rect.width,
|
||||
GetPropertyHeight(property));
|
||||
|
||||
EditorGUI.PropertyField(propertyRect, property, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 574f5fa6033f26342816a8a5f39749e5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/PropertyDrawerBase.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,80 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Text.RegularExpressions;
|
||||
using System;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(ResizableTextAreaAttribute))]
|
||||
public class ResizableTextAreaPropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (property.propertyType == SerializedPropertyType.String)
|
||||
{
|
||||
float labelHeight = EditorGUIUtility.singleLineHeight;
|
||||
float textAreaHeight = GetTextAreaHeight(property.stringValue);
|
||||
return labelHeight + textAreaHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.String)
|
||||
{
|
||||
Rect labelRect = new Rect()
|
||||
{
|
||||
x = rect.x,
|
||||
y = rect.y,
|
||||
width = rect.width,
|
||||
height = EditorGUIUtility.singleLineHeight
|
||||
};
|
||||
|
||||
EditorGUI.LabelField(labelRect, label.text);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
Rect textAreaRect = new Rect()
|
||||
{
|
||||
x = labelRect.x,
|
||||
y = labelRect.y + EditorGUIUtility.singleLineHeight,
|
||||
width = labelRect.width,
|
||||
height = GetTextAreaHeight(property.stringValue)
|
||||
};
|
||||
|
||||
string textAreaValue = EditorGUI.TextArea(textAreaRect, property.stringValue);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
property.stringValue = textAreaValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = typeof(ResizableTextAreaAttribute).Name + " can only be used on string fields";
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
private int GetNumberOfLines(string text)
|
||||
{
|
||||
string content = Regex.Replace(text, @"\r\n|\n\r|\r|\n", Environment.NewLine);
|
||||
string[] lines = content.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
|
||||
return lines.Length;
|
||||
}
|
||||
|
||||
private float GetTextAreaHeight(string text)
|
||||
{
|
||||
float height = (EditorGUIUtility.singleLineHeight - 3.0f) * GetNumberOfLines(text) + 3.0f;
|
||||
return height;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e27ffd9a96b58c46bb74cc93de3e06f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ResizableTextAreaPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,99 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(SceneAttribute))]
|
||||
public class ScenePropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
private const string SceneListItem = "{0} ({1})";
|
||||
private const string ScenePattern = @".+\/(.+)\.unity";
|
||||
private const string TypeWarningMessage = "{0} must be an int or a string";
|
||||
private const string BuildSettingsWarningMessage = "No scenes in the build settings";
|
||||
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
bool validPropertyType = property.propertyType == SerializedPropertyType.String || property.propertyType == SerializedPropertyType.Integer;
|
||||
bool anySceneInBuildSettings = GetScenes().Length > 0;
|
||||
|
||||
return (validPropertyType && anySceneInBuildSettings)
|
||||
? GetPropertyHeight(property)
|
||||
: GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
string[] scenes = GetScenes();
|
||||
bool anySceneInBuildSettings = scenes.Length > 0;
|
||||
if (!anySceneInBuildSettings)
|
||||
{
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, BuildSettingsWarningMessage, MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
string[] sceneOptions = GetSceneOptions(scenes);
|
||||
switch (property.propertyType)
|
||||
{
|
||||
case SerializedPropertyType.String:
|
||||
DrawPropertyForString(rect, property, label, scenes, sceneOptions);
|
||||
break;
|
||||
case SerializedPropertyType.Integer:
|
||||
DrawPropertyForInt(rect, property, label, sceneOptions);
|
||||
break;
|
||||
default:
|
||||
string message = string.Format(TypeWarningMessage, property.name);
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
break;
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
private string[] GetScenes()
|
||||
{
|
||||
return EditorBuildSettings.scenes
|
||||
.Where(scene => scene.enabled)
|
||||
.Select(scene => Regex.Match(scene.path, ScenePattern).Groups[1].Value)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private string[] GetSceneOptions(string[] scenes)
|
||||
{
|
||||
return scenes.Select((s, i) => string.Format(SceneListItem, s, i)).ToArray();
|
||||
}
|
||||
|
||||
private static void DrawPropertyForString(Rect rect, SerializedProperty property, GUIContent label, string[] scenes, string[] sceneOptions)
|
||||
{
|
||||
int index = IndexOf(scenes, property.stringValue);
|
||||
int newIndex = EditorGUI.Popup(rect, label.text, index, sceneOptions);
|
||||
string newScene = scenes[newIndex];
|
||||
|
||||
if (!property.stringValue.Equals(newScene, StringComparison.Ordinal))
|
||||
{
|
||||
property.stringValue = scenes[newIndex];
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawPropertyForInt(Rect rect, SerializedProperty property, GUIContent label, string[] sceneOptions)
|
||||
{
|
||||
int index = property.intValue;
|
||||
int newIndex = EditorGUI.Popup(rect, label.text, index, sceneOptions);
|
||||
|
||||
if (property.intValue != newIndex)
|
||||
{
|
||||
property.intValue = newIndex;
|
||||
}
|
||||
}
|
||||
|
||||
private static int IndexOf(string[] scenes, string scene)
|
||||
{
|
||||
var index = Array.IndexOf(scenes, scene);
|
||||
return Mathf.Clamp(index, 0, scenes.Length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f5ed440d4f429e42a5da7bc5df48fd8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ScenePropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,110 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(ShowAssetPreviewAttribute))]
|
||||
public class ShowAssetPreviewPropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (property.propertyType == SerializedPropertyType.ObjectReference)
|
||||
{
|
||||
Texture2D previewTexture = GetAssetPreview(property);
|
||||
if (previewTexture != null)
|
||||
{
|
||||
return GetPropertyHeight(property) + GetAssetPreviewSize(property).y;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetPropertyHeight(property);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.ObjectReference)
|
||||
{
|
||||
Rect propertyRect = new Rect()
|
||||
{
|
||||
x = rect.x,
|
||||
y = rect.y,
|
||||
width = rect.width,
|
||||
height = EditorGUIUtility.singleLineHeight
|
||||
};
|
||||
|
||||
EditorGUI.PropertyField(propertyRect, property, label);
|
||||
|
||||
Texture2D previewTexture = GetAssetPreview(property);
|
||||
if (previewTexture != null)
|
||||
{
|
||||
Rect previewRect = new Rect()
|
||||
{
|
||||
x = rect.x + NaughtyEditorGUI.GetIndentLength(rect),
|
||||
y = rect.y + EditorGUIUtility.singleLineHeight,
|
||||
width = rect.width,
|
||||
height = GetAssetPreviewSize(property).y
|
||||
};
|
||||
|
||||
GUI.Label(previewRect, previewTexture);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = property.name + " doesn't have an asset preview";
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
private Texture2D GetAssetPreview(SerializedProperty property)
|
||||
{
|
||||
if (property.propertyType == SerializedPropertyType.ObjectReference)
|
||||
{
|
||||
if (property.objectReferenceValue != null)
|
||||
{
|
||||
Texture2D previewTexture = AssetPreview.GetAssetPreview(property.objectReferenceValue);
|
||||
return previewTexture;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Vector2 GetAssetPreviewSize(SerializedProperty property)
|
||||
{
|
||||
Texture2D previewTexture = GetAssetPreview(property);
|
||||
if (previewTexture == null)
|
||||
{
|
||||
return Vector2.zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
int targetWidth = ShowAssetPreviewAttribute.DefaultWidth;
|
||||
int targetHeight = ShowAssetPreviewAttribute.DefaultHeight;
|
||||
|
||||
ShowAssetPreviewAttribute showAssetPreviewAttribute = PropertyUtility.GetAttribute<ShowAssetPreviewAttribute>(property);
|
||||
if (showAssetPreviewAttribute != null)
|
||||
{
|
||||
targetWidth = showAssetPreviewAttribute.Width;
|
||||
targetHeight = showAssetPreviewAttribute.Height;
|
||||
}
|
||||
|
||||
int width = Mathf.Clamp(targetWidth, 0, previewTexture.width);
|
||||
int height = Mathf.Clamp(targetHeight, 0, previewTexture.height);
|
||||
|
||||
return new Vector2(width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24dee3fc91cfe94438de1e3c158f187f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/ShowAssetPreviewPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,91 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(SortingLayerAttribute))]
|
||||
public class SortingLayerPropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
private const string TypeWarningMessage = "{0} must be an int or a string";
|
||||
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
bool validPropertyType = property.propertyType == SerializedPropertyType.String || property.propertyType == SerializedPropertyType.Integer;
|
||||
|
||||
return validPropertyType
|
||||
? GetPropertyHeight(property)
|
||||
: GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
switch (property.propertyType)
|
||||
{
|
||||
case SerializedPropertyType.String:
|
||||
DrawPropertyForString(rect, property, label, GetLayers());
|
||||
break;
|
||||
case SerializedPropertyType.Integer:
|
||||
DrawPropertyForInt(rect, property, label, GetLayers());
|
||||
break;
|
||||
default:
|
||||
string message = string.Format(TypeWarningMessage, property.name);
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
break;
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
private string[] GetLayers()
|
||||
{
|
||||
Type internalEditorUtilityType = typeof(UnityEditorInternal.InternalEditorUtility);
|
||||
PropertyInfo sortingLayersProperty = internalEditorUtilityType.GetProperty("sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
return (string[])sortingLayersProperty.GetValue(null, new object[0]);
|
||||
}
|
||||
|
||||
private static void DrawPropertyForString(Rect rect, SerializedProperty property, GUIContent label, string[] layers)
|
||||
{
|
||||
int index = IndexOf(layers, property.stringValue);
|
||||
int newIndex = EditorGUI.Popup(rect, label.text, index, layers);
|
||||
string newLayer = layers[newIndex];
|
||||
|
||||
if (!property.stringValue.Equals(newLayer, StringComparison.Ordinal))
|
||||
{
|
||||
property.stringValue = layers[newIndex];
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawPropertyForInt(Rect rect, SerializedProperty property, GUIContent label, string[] layers)
|
||||
{
|
||||
int index = 0;
|
||||
string layerName = SortingLayer.IDToName(property.intValue);
|
||||
for (int i = 0; i < layers.Length; i++)
|
||||
{
|
||||
if (layerName.Equals(layers[i], StringComparison.Ordinal))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int newIndex = EditorGUI.Popup(rect, label.text, index, layers);
|
||||
string newLayerName = layers[newIndex];
|
||||
int newLayerNumber = SortingLayer.NameToID(newLayerName);
|
||||
|
||||
if (property.intValue != newLayerNumber)
|
||||
{
|
||||
property.intValue = newLayerNumber;
|
||||
}
|
||||
}
|
||||
|
||||
private static int IndexOf(string[] layers, string layer)
|
||||
{
|
||||
var index = Array.IndexOf(layers, layer);
|
||||
return Mathf.Clamp(index, 0, layers.Length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0ed20ed34d732246a98cde96351fccb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SortingLayerPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,62 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(TagAttribute))]
|
||||
public class TagPropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return (property.propertyType == SerializedPropertyType.String)
|
||||
? GetPropertyHeight(property)
|
||||
: GetPropertyHeight(property) + GetHelpBoxHeight();
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, property);
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.String)
|
||||
{
|
||||
// generate the taglist + custom tags
|
||||
List<string> tagList = new List<string>();
|
||||
tagList.Add("(None)");
|
||||
tagList.Add("Untagged");
|
||||
tagList.AddRange(UnityEditorInternal.InternalEditorUtility.tags);
|
||||
|
||||
string propertyString = property.stringValue;
|
||||
int index = 0;
|
||||
// check if there is an entry that matches the entry and get the index
|
||||
// we skip index 0 as that is a special custom case
|
||||
for (int i = 1; i < tagList.Count; i++)
|
||||
{
|
||||
if (tagList[i].Equals(propertyString, System.StringComparison.Ordinal))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the popup box with the current selected index
|
||||
int newIndex = EditorGUI.Popup(rect, label.text, index, tagList.ToArray());
|
||||
|
||||
// Adjust the actual string value of the property based on the selection
|
||||
string newValue = newIndex > 0 ? tagList[newIndex] : string.Empty;
|
||||
|
||||
if (!property.stringValue.Equals(newValue, System.StringComparison.Ordinal))
|
||||
{
|
||||
property.stringValue = newValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = string.Format("{0} supports only string fields", typeof(TagAttribute).Name);
|
||||
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3df4c068c970ab6498df7a60efbde311
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TagPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 750a102004a7e4f46a2046a3d74cae19
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,205 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public class ReorderableListPropertyDrawer : SpecialCasePropertyDrawerBase
|
||||
{
|
||||
public static readonly ReorderableListPropertyDrawer Instance = new ReorderableListPropertyDrawer();
|
||||
|
||||
private readonly Dictionary<string, ReorderableList> _reorderableListsByPropertyName = new Dictionary<string, ReorderableList>();
|
||||
|
||||
private GUIStyle _labelStyle;
|
||||
|
||||
private GUIStyle GetLabelStyle()
|
||||
{
|
||||
if (_labelStyle == null)
|
||||
{
|
||||
_labelStyle = new GUIStyle(EditorStyles.boldLabel);
|
||||
_labelStyle.richText = true;
|
||||
}
|
||||
|
||||
return _labelStyle;
|
||||
}
|
||||
|
||||
private string GetPropertyKeyName(SerializedProperty property)
|
||||
{
|
||||
return property.serializedObject.targetObject.GetInstanceID() + "." + property.name;
|
||||
}
|
||||
|
||||
protected override float GetPropertyHeight_Internal(SerializedProperty property)
|
||||
{
|
||||
if (property.isArray)
|
||||
{
|
||||
string key = GetPropertyKeyName(property);
|
||||
|
||||
if (_reorderableListsByPropertyName.TryGetValue(key, out ReorderableList reorderableList) == false)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reorderableList.GetHeight();
|
||||
}
|
||||
|
||||
return EditorGUI.GetPropertyHeight(property, true);
|
||||
}
|
||||
|
||||
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (property.isArray)
|
||||
{
|
||||
string key = GetPropertyKeyName(property);
|
||||
|
||||
ReorderableList reorderableList = null;
|
||||
if (!_reorderableListsByPropertyName.ContainsKey(key))
|
||||
{
|
||||
reorderableList = new ReorderableList(property.serializedObject, property, true, true, true, true)
|
||||
{
|
||||
drawHeaderCallback = (Rect r) =>
|
||||
{
|
||||
EditorGUI.LabelField(r, string.Format("{0}: {1}", label.text, property.arraySize), GetLabelStyle());
|
||||
HandleDragAndDrop(r, reorderableList);
|
||||
},
|
||||
|
||||
drawElementCallback = (Rect r, int index, bool isActive, bool isFocused) =>
|
||||
{
|
||||
SerializedProperty element = property.GetArrayElementAtIndex(index);
|
||||
r.y += 1.0f;
|
||||
r.x += 10.0f;
|
||||
r.width -= 10.0f;
|
||||
|
||||
EditorGUI.PropertyField(new Rect(r.x, r.y, r.width, EditorGUIUtility.singleLineHeight), element, true);
|
||||
},
|
||||
|
||||
elementHeightCallback = (int index) =>
|
||||
{
|
||||
return EditorGUI.GetPropertyHeight(property.GetArrayElementAtIndex(index)) + 4.0f;
|
||||
}
|
||||
};
|
||||
|
||||
_reorderableListsByPropertyName[key] = reorderableList;
|
||||
}
|
||||
|
||||
reorderableList = _reorderableListsByPropertyName[key];
|
||||
|
||||
if (rect == default)
|
||||
{
|
||||
reorderableList.DoLayoutList();
|
||||
}
|
||||
else
|
||||
{
|
||||
reorderableList.DoList(rect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = typeof(ReorderableListAttribute).Name + " can be used only on arrays or lists";
|
||||
NaughtyEditorGUI.HelpBox_Layout(message, MessageType.Warning, context: property.serializedObject.targetObject);
|
||||
EditorGUILayout.PropertyField(property, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearCache()
|
||||
{
|
||||
_reorderableListsByPropertyName.Clear();
|
||||
}
|
||||
|
||||
private Object GetAssignableObject(Object obj, ReorderableList list)
|
||||
{
|
||||
System.Type listType = PropertyUtility.GetPropertyType(list.serializedProperty);
|
||||
System.Type elementType = ReflectionUtility.GetListElementType(listType);
|
||||
|
||||
if (elementType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
System.Type objType = obj.GetType();
|
||||
|
||||
if (elementType.IsAssignableFrom(objType))
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (objType == typeof(GameObject))
|
||||
{
|
||||
if (typeof(Transform).IsAssignableFrom(elementType))
|
||||
{
|
||||
Transform transform = ((GameObject)obj).transform;
|
||||
if (elementType == typeof(RectTransform))
|
||||
{
|
||||
RectTransform rectTransform = transform as RectTransform;
|
||||
return rectTransform;
|
||||
}
|
||||
else
|
||||
{
|
||||
return transform;
|
||||
}
|
||||
}
|
||||
else if (typeof(MonoBehaviour).IsAssignableFrom(elementType))
|
||||
{
|
||||
return ((GameObject)obj).GetComponent(elementType);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void HandleDragAndDrop(Rect rect, ReorderableList list)
|
||||
{
|
||||
var currentEvent = Event.current;
|
||||
var usedEvent = false;
|
||||
|
||||
switch (currentEvent.type)
|
||||
{
|
||||
case EventType.DragExited:
|
||||
if (GUI.enabled)
|
||||
{
|
||||
HandleUtility.Repaint();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EventType.DragUpdated:
|
||||
case EventType.DragPerform:
|
||||
if (rect.Contains(currentEvent.mousePosition) && GUI.enabled)
|
||||
{
|
||||
// Check each single object, so we can add multiple objects in a single drag.
|
||||
bool didAcceptDrag = false;
|
||||
Object[] references = DragAndDrop.objectReferences;
|
||||
foreach (Object obj in references)
|
||||
{
|
||||
Object assignableObject = GetAssignableObject(obj, list);
|
||||
if (assignableObject != null)
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
||||
if (currentEvent.type == EventType.DragPerform)
|
||||
{
|
||||
list.serializedProperty.arraySize++;
|
||||
int arrayEnd = list.serializedProperty.arraySize - 1;
|
||||
list.serializedProperty.GetArrayElementAtIndex(arrayEnd).objectReferenceValue = assignableObject;
|
||||
didAcceptDrag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (didAcceptDrag)
|
||||
{
|
||||
GUI.changed = true;
|
||||
DragAndDrop.AcceptDrag();
|
||||
usedEvent = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (usedEvent)
|
||||
{
|
||||
currentEvent.Use();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf36691a6d456564db2fcbfa8726b3f3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers_SpecialCase/ReorderableListPropertyDrawer.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public abstract class SpecialCasePropertyDrawerBase
|
||||
{
|
||||
public void OnGUI(Rect rect, SerializedProperty property)
|
||||
{
|
||||
// Check if visible
|
||||
bool visible = PropertyUtility.IsVisible(property);
|
||||
if (!visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate
|
||||
ValidatorAttribute[] validatorAttributes = PropertyUtility.GetAttributes<ValidatorAttribute>(property);
|
||||
foreach (var validatorAttribute in validatorAttributes)
|
||||
{
|
||||
validatorAttribute.GetValidator().ValidateProperty(property);
|
||||
}
|
||||
|
||||
// Check if enabled and draw
|
||||
EditorGUI.BeginChangeCheck();
|
||||
bool enabled = PropertyUtility.IsEnabled(property);
|
||||
|
||||
using (new EditorGUI.DisabledScope(disabled: !enabled))
|
||||
{
|
||||
OnGUI_Internal(rect, property, PropertyUtility.GetLabel(property));
|
||||
}
|
||||
|
||||
// Call OnValueChanged callbacks
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
PropertyUtility.CallOnValueChangedCallbacks(property);
|
||||
}
|
||||
}
|
||||
|
||||
public float GetPropertyHeight(SerializedProperty property)
|
||||
{
|
||||
return GetPropertyHeight_Internal(property);
|
||||
}
|
||||
|
||||
protected abstract void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label);
|
||||
protected abstract float GetPropertyHeight_Internal(SerializedProperty property);
|
||||
}
|
||||
|
||||
public static class SpecialCaseDrawerAttributeExtensions
|
||||
{
|
||||
private static Dictionary<Type, SpecialCasePropertyDrawerBase> _drawersByAttributeType;
|
||||
|
||||
static SpecialCaseDrawerAttributeExtensions()
|
||||
{
|
||||
_drawersByAttributeType = new Dictionary<Type, SpecialCasePropertyDrawerBase>();
|
||||
_drawersByAttributeType[typeof(ReorderableListAttribute)] = ReorderableListPropertyDrawer.Instance;
|
||||
}
|
||||
|
||||
public static SpecialCasePropertyDrawerBase GetDrawer(this SpecialCaseDrawerAttribute attr)
|
||||
{
|
||||
SpecialCasePropertyDrawerBase drawer;
|
||||
if (_drawersByAttributeType.TryGetValue(attr.GetType(), out drawer))
|
||||
{
|
||||
return drawer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 771776453ad34b045a41dea54856fa12
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers_SpecialCase/SpecialCasePropertyDrawerBase.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41caedece93df91439d624dc9d124424
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,53 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public class MaxValuePropertyValidator : PropertyValidatorBase
|
||||
{
|
||||
public override void ValidateProperty(SerializedProperty property)
|
||||
{
|
||||
MaxValueAttribute maxValueAttribute = PropertyUtility.GetAttribute<MaxValueAttribute>(property);
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.Integer)
|
||||
{
|
||||
if (property.intValue > maxValueAttribute.MaxValue)
|
||||
{
|
||||
property.intValue = (int)maxValueAttribute.MaxValue;
|
||||
}
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Float)
|
||||
{
|
||||
if (property.floatValue > maxValueAttribute.MaxValue)
|
||||
{
|
||||
property.floatValue = maxValueAttribute.MaxValue;
|
||||
}
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector2)
|
||||
{
|
||||
property.vector2Value = Vector2.Min(property.vector2Value, new Vector2(maxValueAttribute.MaxValue, maxValueAttribute.MaxValue));
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector3)
|
||||
{
|
||||
property.vector3Value = Vector3.Min(property.vector3Value, new Vector3(maxValueAttribute.MaxValue, maxValueAttribute.MaxValue, maxValueAttribute.MaxValue));
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector4)
|
||||
{
|
||||
property.vector4Value = Vector4.Min(property.vector4Value, new Vector4(maxValueAttribute.MaxValue, maxValueAttribute.MaxValue, maxValueAttribute.MaxValue, maxValueAttribute.MaxValue));
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector2Int)
|
||||
{
|
||||
property.vector2IntValue = Vector2Int.Min(property.vector2IntValue, new Vector2Int((int)maxValueAttribute.MaxValue, (int)maxValueAttribute.MaxValue));
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector3Int)
|
||||
{
|
||||
property.vector3IntValue = Vector3Int.Min(property.vector3IntValue, new Vector3Int((int)maxValueAttribute.MaxValue, (int)maxValueAttribute.MaxValue, (int)maxValueAttribute.MaxValue));
|
||||
}
|
||||
else
|
||||
{
|
||||
string warning = maxValueAttribute.GetType().Name + " can be used only on int, float, Vector or VectorInt fields";
|
||||
Debug.LogWarning(warning, property.serializedObject.targetObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 627b8e9e7bda6fa408c6f47fb8285665
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyValidators/MaxValuePropertyValidator.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,53 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public class MinValuePropertyValidator : PropertyValidatorBase
|
||||
{
|
||||
public override void ValidateProperty(SerializedProperty property)
|
||||
{
|
||||
MinValueAttribute minValueAttribute = PropertyUtility.GetAttribute<MinValueAttribute>(property);
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.Integer)
|
||||
{
|
||||
if (property.intValue < minValueAttribute.MinValue)
|
||||
{
|
||||
property.intValue = (int)minValueAttribute.MinValue;
|
||||
}
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Float)
|
||||
{
|
||||
if (property.floatValue < minValueAttribute.MinValue)
|
||||
{
|
||||
property.floatValue = minValueAttribute.MinValue;
|
||||
}
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector2)
|
||||
{
|
||||
property.vector2Value = Vector2.Max(property.vector2Value, new Vector2(minValueAttribute.MinValue, minValueAttribute.MinValue));
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector3)
|
||||
{
|
||||
property.vector3Value = Vector3.Max(property.vector3Value, new Vector3(minValueAttribute.MinValue, minValueAttribute.MinValue, minValueAttribute.MinValue));
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector4)
|
||||
{
|
||||
property.vector4Value = Vector4.Max(property.vector4Value, new Vector4(minValueAttribute.MinValue, minValueAttribute.MinValue, minValueAttribute.MinValue, minValueAttribute.MinValue));
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector2Int)
|
||||
{
|
||||
property.vector2IntValue = Vector2Int.Max(property.vector2IntValue, new Vector2Int((int)minValueAttribute.MinValue, (int)minValueAttribute.MinValue));
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector3Int)
|
||||
{
|
||||
property.vector3IntValue = Vector3Int.Max(property.vector3IntValue, new Vector3Int((int)minValueAttribute.MinValue, (int)minValueAttribute.MinValue, (int)minValueAttribute.MinValue));
|
||||
}
|
||||
else
|
||||
{
|
||||
string warning = minValueAttribute.GetType().Name + " can be used only on int, float, Vector or VectorInt fields";
|
||||
Debug.LogWarning(warning, property.serializedObject.targetObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03dd23f6c0598074fb1b721dcd8fe023
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyValidators/MinValuePropertyValidator.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public abstract class PropertyValidatorBase
|
||||
{
|
||||
public abstract void ValidateProperty(SerializedProperty property);
|
||||
}
|
||||
|
||||
public static class ValidatorAttributeExtensions
|
||||
{
|
||||
private static Dictionary<Type, PropertyValidatorBase> _validatorsByAttributeType;
|
||||
|
||||
static ValidatorAttributeExtensions()
|
||||
{
|
||||
_validatorsByAttributeType = new Dictionary<Type, PropertyValidatorBase>();
|
||||
_validatorsByAttributeType[typeof(MinValueAttribute)] = new MinValuePropertyValidator();
|
||||
_validatorsByAttributeType[typeof(MaxValueAttribute)] = new MaxValuePropertyValidator();
|
||||
_validatorsByAttributeType[typeof(RequiredAttribute)] = new RequiredPropertyValidator();
|
||||
_validatorsByAttributeType[typeof(ValidateInputAttribute)] = new ValidateInputPropertyValidator();
|
||||
}
|
||||
|
||||
public static PropertyValidatorBase GetValidator(this ValidatorAttribute attr)
|
||||
{
|
||||
PropertyValidatorBase validator;
|
||||
if (_validatorsByAttributeType.TryGetValue(attr.GetType(), out validator))
|
||||
{
|
||||
return validator;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f332c8e1c3627d742aa9158af7b02ccc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyValidators/PropertyValidatorBase.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,31 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public class RequiredPropertyValidator : PropertyValidatorBase
|
||||
{
|
||||
public override void ValidateProperty(SerializedProperty property)
|
||||
{
|
||||
RequiredAttribute requiredAttribute = PropertyUtility.GetAttribute<RequiredAttribute>(property);
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.ObjectReference)
|
||||
{
|
||||
if (property.objectReferenceValue == null)
|
||||
{
|
||||
string errorMessage = property.name + " is required";
|
||||
if (!string.IsNullOrEmpty(requiredAttribute.Message))
|
||||
{
|
||||
errorMessage = requiredAttribute.Message;
|
||||
}
|
||||
|
||||
NaughtyEditorGUI.HelpBox_Layout(errorMessage, MessageType.Error, context: property.serializedObject.targetObject);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string warning = requiredAttribute.GetType().Name + " works only on reference types";
|
||||
NaughtyEditorGUI.HelpBox_Layout(warning, MessageType.Warning, context: property.serializedObject.targetObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a7e657ea45f6414682b5f41be9541b4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyValidators/RequiredPropertyValidator.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,76 @@
|
||||
using UnityEditor;
|
||||
using System.Reflection;
|
||||
using System;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public class ValidateInputPropertyValidator : PropertyValidatorBase
|
||||
{
|
||||
public override void ValidateProperty(SerializedProperty property)
|
||||
{
|
||||
ValidateInputAttribute validateInputAttribute = PropertyUtility.GetAttribute<ValidateInputAttribute>(property);
|
||||
object target = PropertyUtility.GetTargetObjectWithProperty(property);
|
||||
|
||||
MethodInfo validationCallback = ReflectionUtility.GetMethod(target, validateInputAttribute.CallbackName);
|
||||
|
||||
if (validationCallback != null &&
|
||||
validationCallback.ReturnType == typeof(bool))
|
||||
{
|
||||
ParameterInfo[] callbackParameters = validationCallback.GetParameters();
|
||||
|
||||
if (callbackParameters.Length == 0)
|
||||
{
|
||||
if (!(bool)validationCallback.Invoke(target, null))
|
||||
{
|
||||
if (string.IsNullOrEmpty(validateInputAttribute.Message))
|
||||
{
|
||||
NaughtyEditorGUI.HelpBox_Layout(
|
||||
property.name + " is not valid", MessageType.Error, context: property.serializedObject.targetObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
NaughtyEditorGUI.HelpBox_Layout(
|
||||
validateInputAttribute.Message, MessageType.Error, context: property.serializedObject.targetObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (callbackParameters.Length == 1)
|
||||
{
|
||||
FieldInfo fieldInfo = ReflectionUtility.GetField(target, property.name);
|
||||
Type fieldType = fieldInfo.FieldType;
|
||||
Type parameterType = callbackParameters[0].ParameterType;
|
||||
|
||||
if (fieldType == parameterType)
|
||||
{
|
||||
if (!(bool)validationCallback.Invoke(target, new object[] { fieldInfo.GetValue(target) }))
|
||||
{
|
||||
if (string.IsNullOrEmpty(validateInputAttribute.Message))
|
||||
{
|
||||
NaughtyEditorGUI.HelpBox_Layout(
|
||||
property.name + " is not valid", MessageType.Error, context: property.serializedObject.targetObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
NaughtyEditorGUI.HelpBox_Layout(
|
||||
validateInputAttribute.Message, MessageType.Error, context: property.serializedObject.targetObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string warning = "The field type is not the same as the callback's parameter type";
|
||||
NaughtyEditorGUI.HelpBox_Layout(warning, MessageType.Warning, context: property.serializedObject.targetObject);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string warning =
|
||||
validateInputAttribute.GetType().Name +
|
||||
" needs a callback with boolean return type and an optional single parameter of the same type as the field";
|
||||
|
||||
NaughtyEditorGUI.HelpBox_Layout(warning, MessageType.Warning, context: property.serializedObject.targetObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f6adf84ed53a7840a456e8b4dce38d9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/PropertyValidators/ValidateInputPropertyValidator.cs
|
||||
uploadId: 480834
|
||||
10
Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility.meta
Normal file
10
Assets/Plugins/NaughtyAttributes/Scripts/Editor/Utility.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: acb4475c71a3fe947a81ced84ab89c6d
|
||||
folderAsset: yes
|
||||
timeCreated: 1508062761
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,55 @@
|
||||
using UnityEngine;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public static class ButtonUtility
|
||||
{
|
||||
public static bool IsEnabled(Object target, MethodInfo method)
|
||||
{
|
||||
EnableIfAttributeBase enableIfAttribute = method.GetCustomAttribute<EnableIfAttributeBase>();
|
||||
if (enableIfAttribute == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
List<bool> conditionValues = PropertyUtility.GetConditionValues(target, enableIfAttribute.Conditions);
|
||||
if (conditionValues.Count > 0)
|
||||
{
|
||||
bool enabled = PropertyUtility.GetConditionsFlag(conditionValues, enableIfAttribute.ConditionOperator, enableIfAttribute.Inverted);
|
||||
return enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = enableIfAttribute.GetType().Name + " needs a valid boolean condition field, property or method name to work";
|
||||
Debug.LogWarning(message, target);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsVisible(Object target, MethodInfo method)
|
||||
{
|
||||
ShowIfAttributeBase showIfAttribute = method.GetCustomAttribute<ShowIfAttributeBase>();
|
||||
if (showIfAttribute == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
List<bool> conditionValues = PropertyUtility.GetConditionValues(target, showIfAttribute.Conditions);
|
||||
if (conditionValues.Count > 0)
|
||||
{
|
||||
bool enabled = PropertyUtility.GetConditionsFlag(conditionValues, showIfAttribute.ConditionOperator, showIfAttribute.Inverted);
|
||||
return enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = showIfAttribute.GetType().Name + " needs a valid boolean condition field, property or method name to work";
|
||||
Debug.LogWarning(message, target);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a273f81125ec52d4cb5dec2228afda0e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/Utility/ButtonUtility.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,380 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Experimental.SceneManagement;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public static class NaughtyEditorGUI
|
||||
{
|
||||
public const float IndentLength = 15.0f;
|
||||
public const float HorizontalSpacing = 2.0f;
|
||||
|
||||
private static GUIStyle _buttonStyle = new GUIStyle(GUI.skin.button) { richText = true };
|
||||
|
||||
private delegate void PropertyFieldFunction(Rect rect, SerializedProperty property, GUIContent label, bool includeChildren);
|
||||
|
||||
public static void PropertyField(Rect rect, SerializedProperty property, bool includeChildren)
|
||||
{
|
||||
PropertyField_Implementation(rect, property, includeChildren, DrawPropertyField);
|
||||
}
|
||||
|
||||
public static void PropertyField_Layout(SerializedProperty property, bool includeChildren)
|
||||
{
|
||||
Rect dummyRect = new Rect();
|
||||
PropertyField_Implementation(dummyRect, property, includeChildren, DrawPropertyField_Layout);
|
||||
}
|
||||
|
||||
private static void DrawPropertyField(Rect rect, SerializedProperty property, GUIContent label, bool includeChildren)
|
||||
{
|
||||
EditorGUI.PropertyField(rect, property, label, includeChildren);
|
||||
}
|
||||
|
||||
private static void DrawPropertyField_Layout(Rect rect, SerializedProperty property, GUIContent label, bool includeChildren)
|
||||
{
|
||||
EditorGUILayout.PropertyField(property, label, includeChildren);
|
||||
}
|
||||
|
||||
private static void PropertyField_Implementation(Rect rect, SerializedProperty property, bool includeChildren, PropertyFieldFunction propertyFieldFunction)
|
||||
{
|
||||
SpecialCaseDrawerAttribute specialCaseAttribute = PropertyUtility.GetAttribute<SpecialCaseDrawerAttribute>(property);
|
||||
if (specialCaseAttribute != null)
|
||||
{
|
||||
specialCaseAttribute.GetDrawer().OnGUI(rect, property);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if visible
|
||||
bool visible = PropertyUtility.IsVisible(property);
|
||||
if (!visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate
|
||||
ValidatorAttribute[] validatorAttributes = PropertyUtility.GetAttributes<ValidatorAttribute>(property);
|
||||
foreach (var validatorAttribute in validatorAttributes)
|
||||
{
|
||||
validatorAttribute.GetValidator().ValidateProperty(property);
|
||||
}
|
||||
|
||||
// Check if enabled and draw
|
||||
EditorGUI.BeginChangeCheck();
|
||||
bool enabled = PropertyUtility.IsEnabled(property);
|
||||
|
||||
using (new EditorGUI.DisabledScope(disabled: !enabled))
|
||||
{
|
||||
propertyFieldFunction.Invoke(rect, property, PropertyUtility.GetLabel(property), includeChildren);
|
||||
}
|
||||
|
||||
// Call OnValueChanged callbacks
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
PropertyUtility.CallOnValueChangedCallbacks(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static float GetIndentLength(Rect sourceRect)
|
||||
{
|
||||
Rect indentRect = EditorGUI.IndentedRect(sourceRect);
|
||||
float indentLength = indentRect.x - sourceRect.x;
|
||||
|
||||
return indentLength;
|
||||
}
|
||||
|
||||
public static void BeginBoxGroup_Layout(string label = "")
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
if (!string.IsNullOrEmpty(label))
|
||||
{
|
||||
EditorGUILayout.LabelField(label, EditorStyles.boldLabel);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EndBoxGroup_Layout()
|
||||
{
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a dropdown
|
||||
/// </summary>
|
||||
/// <param name="rect">The rect the defines the position and size of the dropdown in the inspector</param>
|
||||
/// <param name="serializedObject">The serialized object that is being updated</param>
|
||||
/// <param name="target">The target object that contains the dropdown</param>
|
||||
/// <param name="dropdownField">The field of the target object that holds the currently selected dropdown value</param>
|
||||
/// <param name="label">The label of the dropdown</param>
|
||||
/// <param name="selectedValueIndex">The index of the value from the values array</param>
|
||||
/// <param name="values">The values of the dropdown</param>
|
||||
/// <param name="displayOptions">The display options for the values</param>
|
||||
public static void Dropdown(
|
||||
Rect rect, SerializedObject serializedObject, object target, FieldInfo dropdownField,
|
||||
string label, int selectedValueIndex, object[] values, string[] displayOptions)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
int newIndex = EditorGUI.Popup(rect, label, selectedValueIndex, displayOptions);
|
||||
object newValue = values[newIndex];
|
||||
|
||||
object dropdownValue = dropdownField.GetValue(target);
|
||||
if (dropdownValue == null || !dropdownValue.Equals(newValue))
|
||||
{
|
||||
Undo.RecordObject(serializedObject.targetObject, "Dropdown");
|
||||
|
||||
// TODO: Problem with structs, because they are value type.
|
||||
// The solution is to make boxing/unboxing but unfortunately I don't know the compile time type of the target object
|
||||
dropdownField.SetValue(target, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Button(UnityEngine.Object target, MethodInfo methodInfo)
|
||||
{
|
||||
bool visible = ButtonUtility.IsVisible(target, methodInfo);
|
||||
if (!visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (methodInfo.GetParameters().All(p => p.IsOptional))
|
||||
{
|
||||
ButtonAttribute buttonAttribute = (ButtonAttribute)methodInfo.GetCustomAttributes(typeof(ButtonAttribute), true)[0];
|
||||
string buttonText = string.IsNullOrEmpty(buttonAttribute.Text) ? ObjectNames.NicifyVariableName(methodInfo.Name) : buttonAttribute.Text;
|
||||
|
||||
bool buttonEnabled = ButtonUtility.IsEnabled(target, methodInfo);
|
||||
|
||||
EButtonEnableMode mode = buttonAttribute.SelectedEnableMode;
|
||||
buttonEnabled &=
|
||||
mode == EButtonEnableMode.Always ||
|
||||
mode == EButtonEnableMode.Editor && !Application.isPlaying ||
|
||||
mode == EButtonEnableMode.Playmode && Application.isPlaying;
|
||||
|
||||
bool methodIsCoroutine = methodInfo.ReturnType == typeof(IEnumerator);
|
||||
if (methodIsCoroutine)
|
||||
{
|
||||
buttonEnabled &= (Application.isPlaying ? true : false);
|
||||
}
|
||||
|
||||
EditorGUI.BeginDisabledGroup(!buttonEnabled);
|
||||
|
||||
if (GUILayout.Button(buttonText, _buttonStyle))
|
||||
{
|
||||
object[] defaultParams = methodInfo.GetParameters().Select(p => p.DefaultValue).ToArray();
|
||||
IEnumerator methodResult = methodInfo.Invoke(target, defaultParams) as IEnumerator;
|
||||
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
// Set target object and scene dirty to serialize changes to disk
|
||||
EditorUtility.SetDirty(target);
|
||||
|
||||
PrefabStage stage = PrefabStageUtility.GetCurrentPrefabStage();
|
||||
if (stage != null)
|
||||
{
|
||||
// Prefab mode
|
||||
EditorSceneManager.MarkSceneDirty(stage.scene);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal scene
|
||||
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
|
||||
}
|
||||
}
|
||||
else if (methodResult != null && target is MonoBehaviour behaviour)
|
||||
{
|
||||
behaviour.StartCoroutine(methodResult);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
else
|
||||
{
|
||||
string warning = typeof(ButtonAttribute).Name + " works only on methods with no parameters";
|
||||
HelpBox_Layout(warning, MessageType.Warning, context: target, logToConsole: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void NativeProperty_Layout(UnityEngine.Object target, PropertyInfo property)
|
||||
{
|
||||
object value = property.GetValue(target, null);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
string warning = string.Format("{0} is null. {1} doesn't support reference types with null value", ObjectNames.NicifyVariableName(property.Name), typeof(ShowNativePropertyAttribute).Name);
|
||||
HelpBox_Layout(warning, MessageType.Warning, context: target);
|
||||
}
|
||||
else if (!Field_Layout(value, ObjectNames.NicifyVariableName(property.Name)))
|
||||
{
|
||||
string warning = string.Format("{0} doesn't support {1} types", typeof(ShowNativePropertyAttribute).Name, property.PropertyType.Name);
|
||||
HelpBox_Layout(warning, MessageType.Warning, context: target);
|
||||
}
|
||||
}
|
||||
|
||||
public static void NonSerializedField_Layout(UnityEngine.Object target, FieldInfo field)
|
||||
{
|
||||
object value = field.GetValue(target);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
string warning = string.Format("{0} is null. {1} doesn't support reference types with null value", ObjectNames.NicifyVariableName(field.Name), typeof(ShowNonSerializedFieldAttribute).Name);
|
||||
HelpBox_Layout(warning, MessageType.Warning, context: target);
|
||||
}
|
||||
else if (!Field_Layout(value, ObjectNames.NicifyVariableName(field.Name)))
|
||||
{
|
||||
string warning = string.Format("{0} doesn't support {1} types", typeof(ShowNonSerializedFieldAttribute).Name, field.FieldType.Name);
|
||||
HelpBox_Layout(warning, MessageType.Warning, context: target);
|
||||
}
|
||||
}
|
||||
|
||||
public static void HorizontalLine(Rect rect, float height, Color color)
|
||||
{
|
||||
rect.height = height;
|
||||
EditorGUI.DrawRect(rect, color);
|
||||
}
|
||||
|
||||
public static void HelpBox(Rect rect, string message, MessageType type, UnityEngine.Object context = null, bool logToConsole = false)
|
||||
{
|
||||
EditorGUI.HelpBox(rect, message, type);
|
||||
|
||||
if (logToConsole)
|
||||
{
|
||||
DebugLogMessage(message, type, context);
|
||||
}
|
||||
}
|
||||
|
||||
public static void HelpBox_Layout(string message, MessageType type, UnityEngine.Object context = null, bool logToConsole = false)
|
||||
{
|
||||
EditorGUILayout.HelpBox(message, type);
|
||||
|
||||
if (logToConsole)
|
||||
{
|
||||
DebugLogMessage(message, type, context);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Field_Layout(object value, string label)
|
||||
{
|
||||
using (new EditorGUI.DisabledScope(disabled: true))
|
||||
{
|
||||
bool isDrawn = true;
|
||||
Type valueType = value.GetType();
|
||||
|
||||
if (valueType == typeof(bool))
|
||||
{
|
||||
EditorGUILayout.Toggle(label, (bool)value);
|
||||
}
|
||||
else if (valueType == typeof(short))
|
||||
{
|
||||
EditorGUILayout.IntField(label, (short)value);
|
||||
}
|
||||
else if (valueType == typeof(ushort))
|
||||
{
|
||||
EditorGUILayout.IntField(label, (ushort)value);
|
||||
}
|
||||
else if (valueType == typeof(int))
|
||||
{
|
||||
EditorGUILayout.IntField(label, (int)value);
|
||||
}
|
||||
else if (valueType == typeof(uint))
|
||||
{
|
||||
EditorGUILayout.LongField(label, (uint)value);
|
||||
}
|
||||
else if (valueType == typeof(long))
|
||||
{
|
||||
EditorGUILayout.LongField(label, (long)value);
|
||||
}
|
||||
else if (valueType == typeof(ulong))
|
||||
{
|
||||
EditorGUILayout.TextField(label, ((ulong)value).ToString());
|
||||
}
|
||||
else if (valueType == typeof(float))
|
||||
{
|
||||
EditorGUILayout.FloatField(label, (float)value);
|
||||
}
|
||||
else if (valueType == typeof(double))
|
||||
{
|
||||
EditorGUILayout.DoubleField(label, (double)value);
|
||||
}
|
||||
else if (valueType == typeof(string))
|
||||
{
|
||||
EditorGUILayout.TextField(label, (string)value);
|
||||
}
|
||||
else if (valueType == typeof(Vector2))
|
||||
{
|
||||
EditorGUILayout.Vector2Field(label, (Vector2)value);
|
||||
}
|
||||
else if (valueType == typeof(Vector3))
|
||||
{
|
||||
EditorGUILayout.Vector3Field(label, (Vector3)value);
|
||||
}
|
||||
else if (valueType == typeof(Vector4))
|
||||
{
|
||||
EditorGUILayout.Vector4Field(label, (Vector4)value);
|
||||
}
|
||||
else if (valueType == typeof(Vector2Int))
|
||||
{
|
||||
EditorGUILayout.Vector2IntField(label, (Vector2Int)value);
|
||||
}
|
||||
else if (valueType == typeof(Vector3Int))
|
||||
{
|
||||
EditorGUILayout.Vector3IntField(label, (Vector3Int)value);
|
||||
}
|
||||
else if (valueType == typeof(Color))
|
||||
{
|
||||
EditorGUILayout.ColorField(label, (Color)value);
|
||||
}
|
||||
else if (valueType == typeof(Bounds))
|
||||
{
|
||||
EditorGUILayout.BoundsField(label, (Bounds)value);
|
||||
}
|
||||
else if (valueType == typeof(Rect))
|
||||
{
|
||||
EditorGUILayout.RectField(label, (Rect)value);
|
||||
}
|
||||
else if (valueType == typeof(RectInt))
|
||||
{
|
||||
EditorGUILayout.RectIntField(label, (RectInt)value);
|
||||
}
|
||||
else if (typeof(UnityEngine.Object).IsAssignableFrom(valueType))
|
||||
{
|
||||
EditorGUILayout.ObjectField(label, (UnityEngine.Object)value, valueType, true);
|
||||
}
|
||||
else if (valueType.BaseType == typeof(Enum))
|
||||
{
|
||||
EditorGUILayout.EnumPopup(label, (Enum)value);
|
||||
}
|
||||
else if (valueType.BaseType == typeof(System.Reflection.TypeInfo))
|
||||
{
|
||||
EditorGUILayout.TextField(label, value.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
isDrawn = false;
|
||||
}
|
||||
|
||||
return isDrawn;
|
||||
}
|
||||
}
|
||||
|
||||
private static void DebugLogMessage(string message, MessageType type, UnityEngine.Object context)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MessageType.None:
|
||||
case MessageType.Info:
|
||||
Debug.Log(message, context);
|
||||
break;
|
||||
case MessageType.Warning:
|
||||
Debug.LogWarning(message, context);
|
||||
break;
|
||||
case MessageType.Error:
|
||||
Debug.LogError(message, context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ff27ff7705d6064e935bb2159a1b453
|
||||
timeCreated: 1510926159
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/Utility/NaughtyEditorGUI.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,374 @@
|
||||
using UnityEditor;
|
||||
using System.Reflection;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public static class PropertyUtility
|
||||
{
|
||||
public static T GetAttribute<T>(SerializedProperty property) where T : class
|
||||
{
|
||||
T[] attributes = GetAttributes<T>(property);
|
||||
return (attributes.Length > 0) ? attributes[0] : null;
|
||||
}
|
||||
|
||||
public static T[] GetAttributes<T>(SerializedProperty property) where T : class
|
||||
{
|
||||
FieldInfo fieldInfo = ReflectionUtility.GetField(GetTargetObjectWithProperty(property), property.name);
|
||||
if (fieldInfo == null)
|
||||
{
|
||||
return new T[] { };
|
||||
}
|
||||
|
||||
return (T[])fieldInfo.GetCustomAttributes(typeof(T), true);
|
||||
}
|
||||
|
||||
public static GUIContent GetLabel(SerializedProperty property)
|
||||
{
|
||||
LabelAttribute labelAttribute = GetAttribute<LabelAttribute>(property);
|
||||
string labelText = (labelAttribute == null)
|
||||
? property.displayName
|
||||
: labelAttribute.Label;
|
||||
|
||||
GUIContent label = new GUIContent(labelText);
|
||||
return label;
|
||||
}
|
||||
|
||||
public static void CallOnValueChangedCallbacks(SerializedProperty property)
|
||||
{
|
||||
OnValueChangedAttribute[] onValueChangedAttributes = GetAttributes<OnValueChangedAttribute>(property);
|
||||
if (onValueChangedAttributes.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
object target = GetTargetObjectWithProperty(property);
|
||||
property.serializedObject.ApplyModifiedProperties(); // We must apply modifications so that the new value is updated in the serialized object
|
||||
|
||||
foreach (var onValueChangedAttribute in onValueChangedAttributes)
|
||||
{
|
||||
MethodInfo callbackMethod = ReflectionUtility.GetMethod(target, onValueChangedAttribute.CallbackName);
|
||||
if (callbackMethod != null &&
|
||||
callbackMethod.ReturnType == typeof(void) &&
|
||||
callbackMethod.GetParameters().Length == 0)
|
||||
{
|
||||
callbackMethod.Invoke(target, new object[] { });
|
||||
}
|
||||
else
|
||||
{
|
||||
string warning = string.Format(
|
||||
"{0} can invoke only methods with 'void' return type and 0 parameters",
|
||||
onValueChangedAttribute.GetType().Name);
|
||||
|
||||
Debug.LogWarning(warning, property.serializedObject.targetObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsEnabled(SerializedProperty property)
|
||||
{
|
||||
ReadOnlyAttribute readOnlyAttribute = GetAttribute<ReadOnlyAttribute>(property);
|
||||
if (readOnlyAttribute != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
EnableIfAttributeBase enableIfAttribute = GetAttribute<EnableIfAttributeBase>(property);
|
||||
if (enableIfAttribute == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
object target = GetTargetObjectWithProperty(property);
|
||||
|
||||
// deal with enum conditions
|
||||
if (enableIfAttribute.EnumValue != null)
|
||||
{
|
||||
Enum value = GetEnumValue(target, enableIfAttribute.Conditions[0]);
|
||||
if (value != null)
|
||||
{
|
||||
bool matched = value.GetType().GetCustomAttribute<FlagsAttribute>() == null
|
||||
? enableIfAttribute.EnumValue.Equals(value)
|
||||
: value.HasFlag(enableIfAttribute.EnumValue);
|
||||
|
||||
return matched != enableIfAttribute.Inverted;
|
||||
}
|
||||
|
||||
string message = enableIfAttribute.GetType().Name + " needs a valid enum field, property or method name to work";
|
||||
Debug.LogWarning(message, property.serializedObject.targetObject);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// deal with normal conditions
|
||||
List<bool> conditionValues = GetConditionValues(target, enableIfAttribute.Conditions);
|
||||
if (conditionValues.Count > 0)
|
||||
{
|
||||
bool enabled = GetConditionsFlag(conditionValues, enableIfAttribute.ConditionOperator, enableIfAttribute.Inverted);
|
||||
return enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = enableIfAttribute.GetType().Name + " needs a valid boolean condition field, property or method name to work";
|
||||
Debug.LogWarning(message, property.serializedObject.targetObject);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsVisible(SerializedProperty property)
|
||||
{
|
||||
ShowIfAttributeBase showIfAttribute = GetAttribute<ShowIfAttributeBase>(property);
|
||||
if (showIfAttribute == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
object target = GetTargetObjectWithProperty(property);
|
||||
|
||||
// deal with enum conditions
|
||||
if (showIfAttribute.EnumValue != null)
|
||||
{
|
||||
Enum value = GetEnumValue(target, showIfAttribute.Conditions[0]);
|
||||
if (value != null)
|
||||
{
|
||||
bool matched = value.GetType().GetCustomAttribute<FlagsAttribute>() == null
|
||||
? showIfAttribute.EnumValue.Equals(value)
|
||||
: value.HasFlag(showIfAttribute.EnumValue);
|
||||
|
||||
return matched != showIfAttribute.Inverted;
|
||||
}
|
||||
|
||||
string message = showIfAttribute.GetType().Name + " needs a valid enum field, property or method name to work";
|
||||
Debug.LogWarning(message, property.serializedObject.targetObject);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// deal with normal conditions
|
||||
List<bool> conditionValues = GetConditionValues(target, showIfAttribute.Conditions);
|
||||
if (conditionValues.Count > 0)
|
||||
{
|
||||
bool enabled = GetConditionsFlag(conditionValues, showIfAttribute.ConditionOperator, showIfAttribute.Inverted);
|
||||
return enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = showIfAttribute.GetType().Name + " needs a valid boolean condition field, property or method name to work";
|
||||
Debug.LogWarning(message, property.serializedObject.targetObject);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enum value from reflection.
|
||||
/// </summary>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <param name="enumName">Name of a field, property, or method that returns an enum.</param>
|
||||
/// <returns>Null if can't find an enum value.</returns>
|
||||
internal static Enum GetEnumValue(object target, string enumName)
|
||||
{
|
||||
FieldInfo enumField = ReflectionUtility.GetField(target, enumName);
|
||||
if (enumField != null && enumField.FieldType.IsSubclassOf(typeof(Enum)))
|
||||
{
|
||||
return (Enum)enumField.GetValue(target);
|
||||
}
|
||||
|
||||
PropertyInfo enumProperty = ReflectionUtility.GetProperty(target, enumName);
|
||||
if (enumProperty != null && enumProperty.PropertyType.IsSubclassOf(typeof(Enum)))
|
||||
{
|
||||
return (Enum)enumProperty.GetValue(target);
|
||||
}
|
||||
|
||||
MethodInfo enumMethod = ReflectionUtility.GetMethod(target, enumName);
|
||||
if (enumMethod != null && enumMethod.ReturnType.IsSubclassOf(typeof(Enum)))
|
||||
{
|
||||
return (Enum)enumMethod.Invoke(target, null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static List<bool> GetConditionValues(object target, string[] conditions)
|
||||
{
|
||||
List<bool> conditionValues = new List<bool>();
|
||||
foreach (var condition in conditions)
|
||||
{
|
||||
FieldInfo conditionField = ReflectionUtility.GetField(target, condition);
|
||||
if (conditionField != null &&
|
||||
conditionField.FieldType == typeof(bool))
|
||||
{
|
||||
conditionValues.Add((bool)conditionField.GetValue(target));
|
||||
}
|
||||
|
||||
PropertyInfo conditionProperty = ReflectionUtility.GetProperty(target, condition);
|
||||
if (conditionProperty != null &&
|
||||
conditionProperty.PropertyType == typeof(bool))
|
||||
{
|
||||
conditionValues.Add((bool)conditionProperty.GetValue(target));
|
||||
}
|
||||
|
||||
MethodInfo conditionMethod = ReflectionUtility.GetMethod(target, condition);
|
||||
if (conditionMethod != null &&
|
||||
conditionMethod.ReturnType == typeof(bool) &&
|
||||
conditionMethod.GetParameters().Length == 0)
|
||||
{
|
||||
conditionValues.Add((bool)conditionMethod.Invoke(target, null));
|
||||
}
|
||||
}
|
||||
|
||||
return conditionValues;
|
||||
}
|
||||
|
||||
internal static bool GetConditionsFlag(List<bool> conditionValues, EConditionOperator conditionOperator, bool invert)
|
||||
{
|
||||
bool flag;
|
||||
if (conditionOperator == EConditionOperator.And)
|
||||
{
|
||||
flag = true;
|
||||
foreach (var value in conditionValues)
|
||||
{
|
||||
flag = flag && value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flag = false;
|
||||
foreach (var value in conditionValues)
|
||||
{
|
||||
flag = flag || value;
|
||||
}
|
||||
}
|
||||
|
||||
if (invert)
|
||||
{
|
||||
flag = !flag;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
public static Type GetPropertyType(SerializedProperty property)
|
||||
{
|
||||
object obj = GetTargetObjectOfProperty(property);
|
||||
Type objType = obj.GetType();
|
||||
|
||||
return objType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the object the property represents.
|
||||
/// </summary>
|
||||
/// <param name="property"></param>
|
||||
/// <returns></returns>
|
||||
public static object GetTargetObjectOfProperty(SerializedProperty property)
|
||||
{
|
||||
if (property == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string path = property.propertyPath.Replace(".Array.data[", "[");
|
||||
object obj = property.serializedObject.targetObject;
|
||||
string[] elements = path.Split('.');
|
||||
|
||||
foreach (var element in elements)
|
||||
{
|
||||
if (element.Contains("["))
|
||||
{
|
||||
string elementName = element.Substring(0, element.IndexOf("["));
|
||||
int index = Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", ""));
|
||||
obj = GetValue_Imp(obj, elementName, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = GetValue_Imp(obj, element);
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the object that the property is a member of
|
||||
/// </summary>
|
||||
/// <param name="property"></param>
|
||||
/// <returns></returns>
|
||||
public static object GetTargetObjectWithProperty(SerializedProperty property)
|
||||
{
|
||||
string path = property.propertyPath.Replace(".Array.data[", "[");
|
||||
object obj = property.serializedObject.targetObject;
|
||||
string[] elements = path.Split('.');
|
||||
|
||||
for (int i = 0; i < elements.Length - 1; i++)
|
||||
{
|
||||
string element = elements[i];
|
||||
if (element.Contains("["))
|
||||
{
|
||||
string elementName = element.Substring(0, element.IndexOf("["));
|
||||
int index = Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", ""));
|
||||
obj = GetValue_Imp(obj, elementName, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = GetValue_Imp(obj, element);
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private static object GetValue_Imp(object source, string name)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Type type = source.GetType();
|
||||
|
||||
while (type != null)
|
||||
{
|
||||
FieldInfo field = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
if (field != null)
|
||||
{
|
||||
return field.GetValue(source);
|
||||
}
|
||||
|
||||
PropertyInfo property = type.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||
if (property != null)
|
||||
{
|
||||
return property.GetValue(source, null);
|
||||
}
|
||||
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static object GetValue_Imp(object source, string name, int index)
|
||||
{
|
||||
IEnumerable enumerable = GetValue_Imp(source, name) as IEnumerable;
|
||||
if (enumerable == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IEnumerator enumerator = enumerable.GetEnumerator();
|
||||
for (int i = 0; i <= index; i++)
|
||||
{
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return enumerator.Current;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 312eedcb79c7a5542b87c0b848e3e2fa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/Utility/PropertyUtility.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,128 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
public static class ReflectionUtility
|
||||
{
|
||||
public static IEnumerable<FieldInfo> GetAllFields(object target, Func<FieldInfo, bool> predicate)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
Debug.LogError("The target object is null. Check for missing scripts.");
|
||||
yield break;
|
||||
}
|
||||
|
||||
List<Type> types = GetSelfAndBaseTypes(target);
|
||||
|
||||
for (int i = types.Count - 1; i >= 0; i--)
|
||||
{
|
||||
IEnumerable<FieldInfo> fieldInfos = types[i]
|
||||
.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly)
|
||||
.Where(predicate);
|
||||
|
||||
foreach (var fieldInfo in fieldInfos)
|
||||
{
|
||||
yield return fieldInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<PropertyInfo> GetAllProperties(object target, Func<PropertyInfo, bool> predicate)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
Debug.LogError("The target object is null. Check for missing scripts.");
|
||||
yield break;
|
||||
}
|
||||
|
||||
List<Type> types = GetSelfAndBaseTypes(target);
|
||||
|
||||
for (int i = types.Count - 1; i >= 0; i--)
|
||||
{
|
||||
IEnumerable<PropertyInfo> propertyInfos = types[i]
|
||||
.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly)
|
||||
.Where(predicate);
|
||||
|
||||
foreach (var propertyInfo in propertyInfos)
|
||||
{
|
||||
yield return propertyInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<MethodInfo> GetAllMethods(object target, Func<MethodInfo, bool> predicate)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
Debug.LogError("The target object is null. Check for missing scripts.");
|
||||
yield break;
|
||||
}
|
||||
|
||||
List<Type> types = GetSelfAndBaseTypes(target);
|
||||
|
||||
for (int i = types.Count - 1; i >= 0; i--)
|
||||
{
|
||||
IEnumerable<MethodInfo> methodInfos = types[i]
|
||||
.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly)
|
||||
.Where(predicate);
|
||||
|
||||
foreach (var methodInfo in methodInfos)
|
||||
{
|
||||
yield return methodInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static FieldInfo GetField(object target, string fieldName)
|
||||
{
|
||||
return GetAllFields(target, f => f.Name.Equals(fieldName, StringComparison.Ordinal)).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static PropertyInfo GetProperty(object target, string propertyName)
|
||||
{
|
||||
return GetAllProperties(target, p => p.Name.Equals(propertyName, StringComparison.Ordinal)).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static MethodInfo GetMethod(object target, string methodName)
|
||||
{
|
||||
return GetAllMethods(target, m => m.Name.Equals(methodName, StringComparison.Ordinal)).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static Type GetListElementType(Type listType)
|
||||
{
|
||||
if (listType.IsGenericType)
|
||||
{
|
||||
return listType.GetGenericArguments()[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return listType.GetElementType();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get type and all base types of target, sorted as following:
|
||||
/// <para />[target's type, base type, base's base type, ...]
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <returns></returns>
|
||||
private static List<Type> GetSelfAndBaseTypes(object target)
|
||||
{
|
||||
List<Type> types = new List<Type>()
|
||||
{
|
||||
target.GetType()
|
||||
};
|
||||
|
||||
while (types.Last().BaseType != null)
|
||||
{
|
||||
types.Add(types.Last().BaseType);
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d86c581f02a55f458e36bf7e81e3084
|
||||
timeCreated: 1520258793
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/Utility/ReflectionUtility.cs
|
||||
uploadId: 480834
|
||||
@@ -0,0 +1,34 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace NaughtyAttributes.Editor
|
||||
{
|
||||
internal class SavedBool
|
||||
{
|
||||
private bool _value;
|
||||
private string _name;
|
||||
|
||||
public bool Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_value == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_value = value;
|
||||
EditorPrefs.SetBool(_name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public SavedBool(string name, bool value)
|
||||
{
|
||||
_name = name;
|
||||
_value = EditorPrefs.GetBool(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18613afe66b0c0344a2be5f430bf965a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129996
|
||||
packageName: NaughtyAttributes
|
||||
packageVersion: 2.1.4
|
||||
assetPath: Assets/NaughtyAttributes/Scripts/Editor/Utility/SavedBool.cs
|
||||
uploadId: 480834
|
||||
Reference in New Issue
Block a user