From 369eb572e54a8f0a1308e3bee3454a4eafb92647 Mon Sep 17 00:00:00 2001 From: apilola Date: Tue, 15 Aug 2023 11:54:35 -0400 Subject: [PATCH] Added Typed Dropdown boiler plate --- .../TypedDropdownAttribute.cs | 26 +++ .../TypedDropdownAttribute.cs.meta | 11 ++ .../SerializedReferencePropertyDrawerBase.cs | 152 ++++++++++++++++++ ...ializedReferencePropertyDrawerBase.cs.meta | 11 ++ .../TypeDropdownAttributePropertyDrawer.cs | 15 ++ ...ypeDropdownAttributePropertyDrawer.cs.meta | 11 ++ .../Scripts/Test/TypedDropdownTest.cs | 30 ++++ .../Scripts/Test/TypedDropdownTest.cs.meta | 11 ++ 8 files changed, 267 insertions(+) create mode 100644 Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs create mode 100644 Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs.meta create mode 100644 Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs create mode 100644 Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs.meta create mode 100644 Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs create mode 100644 Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs.meta create mode 100644 Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs create mode 100644 Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs.meta diff --git a/Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs b/Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs new file mode 100644 index 00000000..4aebead9 --- /dev/null +++ b/Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs @@ -0,0 +1,26 @@ +#if UNITY_2021_3_OR_NEWER +using UnityEngine; +using System; + +namespace NaughtyAttributes +{ + /// + /// Draws a dropdown with all types derived from the given base type + /// + public class TypeDropdownAttribute : PropertyAttribute + { + public readonly Type baseType; + public readonly Type defaultType; + public TypeDropdownAttribute(Type baseType) : this(baseType, baseType) + { + + } + + public TypeDropdownAttribute(Type baseType, Type defaultType) + { + this.baseType = baseType; + this.defaultType = defaultType; + } + } +} +#endif \ No newline at end of file diff --git a/Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs.meta b/Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs.meta new file mode 100644 index 00000000..c70fab88 --- /dev/null +++ b/Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 661f75eeab4377143834b7b532f7f49a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs new file mode 100644 index 00000000..1d3cfd4e --- /dev/null +++ b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs @@ -0,0 +1,152 @@ +#if UNITY_2021_3_OR_NEWER +using UnityEngine; +using System; +using System.Collections.Generic; +using UnityEditor; + +namespace NaughtyAttributes +{ + public abstract class SerializedReferencePropertyDrawerBase : PropertyDrawer + { + static float lineHeight => EditorGUIUtility.singleLineHeight; + static float verticalSpacing => EditorGUIUtility.standardVerticalSpacing; + protected abstract System.Type DefaultType { get; } + protected abstract System.Type BaseType { get; } + + System.Collections.Generic.List m_Types = new List(); + + bool m_Initialized = false; + + /// + /// If you override OnGUI or GetPropertyHeight, you should call this method first + /// + protected void Init() + { + if (m_Initialized) + return; + + CollectTypes(m_Types); + Initialize(); + + m_Initialized = true; + } + + /// + /// Called after types are collected. Can be used to initialze custom fields + /// + protected virtual void Initialize() + { + + } + + /// + /// Called during initialization to collect types. Can be overriden to provide custom types + /// + /// + protected virtual void CollectTypes(List list) + { + var assemblies = System.AppDomain.CurrentDomain.GetAssemblies(); + foreach (var assembly in assemblies) + { + foreach (var type in assembly.GetTypes()) + { + if (BaseType.IsAssignableFrom(type) && !type.IsGenericType && !type.IsAbstract && type.AssemblyQualifiedName != DefaultType.AssemblyQualifiedName) + { + m_Types.Add(type); + } + } + } + } + + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + Init(); + + EditorGUI.BeginProperty(position, label, property); + + var dropDownRect = position; + dropDownRect.height = lineHeight; + dropDownRect.x += EditorGUIUtility.labelWidth + verticalSpacing; + dropDownRect.width -= EditorGUIUtility.labelWidth + verticalSpacing; + + DrawDropdpownContent(dropDownRect, property); + + EditorGUI.PropertyField(position, property, label, true); + EditorGUI.EndProperty(); + } + + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + Init(); + return EditorGUI.GetPropertyHeight(property); + } + + public void DrawDropdpownContent(Rect position, SerializedProperty property) + { + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isPaused); + + var oCol = GUI.contentColor; + if (property.managedReferenceValue == null) + { + FillProperty(property, DefaultType); + } + + var currentObject = property.managedReferenceValue; + var currentSelectorType = currentObject.GetType(); + var currentContent = GetGUIContentForType(currentSelectorType); + + var rect = position; + + if (EditorGUI.DropdownButton(rect, currentContent, FocusType.Keyboard)) + { + GenericMenu menu = new GenericMenu(); + for (var i = 0; i < m_Types.Count; i++) + { + var type = m_Types[i]; + var content = GetGUIContentForType(type); + bool isOn = currentContent.text == content.text; + menu.AddItem(content, currentContent.text == content.text, () => + { + if (!isOn) + { + FillProperty(property, type); + } + }); + } + + menu.AddSeparator(null); + + var defaultContent = GetGUIContentForType(DefaultType); + bool defaultIsOn = defaultContent.text == currentContent.text; + menu.AddItem(GetGUIContentForType(DefaultType), defaultIsOn, () => + { + if (!defaultIsOn) + { + FillProperty(property, DefaultType); + } + }); + menu.DropDown(rect); + } + + GUI.contentColor = oCol; + + GUIContent GetGUIContentForType(System.Type type) + { + if (type.AssemblyQualifiedName == DefaultType.AssemblyQualifiedName) + return new GUIContent($"{type.Name} (Default)"); + return new GUIContent($"{type.Name}"); + } + EditorGUI.EndDisabledGroup(); + } + + private static void FillProperty(SerializedProperty property, System.Type type) + { + var newAsset = Activator.CreateInstance(type); + property.managedReferenceValue = newAsset; + property.serializedObject.ApplyModifiedProperties(); + } + } +} +#endif \ No newline at end of file diff --git a/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs.meta b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs.meta new file mode 100644 index 00000000..910753aa --- /dev/null +++ b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae70e28dde71d0040bb2e2ce2c031857 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs new file mode 100644 index 00000000..43c8e725 --- /dev/null +++ b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs @@ -0,0 +1,15 @@ +#if UNITY_2021_3_OR_NEWER +using System; +using UnityEditor; + +namespace NaughtyAttributes +{ + + [CustomPropertyDrawer(typeof(TypeDropdownAttribute))] + public class TypeDropdownAttributePropertyDrawer : SerializedReferencePropertyDrawerBase + { + protected override Type DefaultType => (attribute as TypeDropdownAttribute).defaultType; + protected override Type BaseType => (attribute as TypeDropdownAttribute).baseType; + } +} +#endif diff --git a/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs.meta b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs.meta new file mode 100644 index 00000000..83a41f2f --- /dev/null +++ b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 18b307637a2c2d54dbd7db3c2f3a4e9c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs b/Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs new file mode 100644 index 00000000..b9bde135 --- /dev/null +++ b/Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs @@ -0,0 +1,30 @@ +#if UNITY_2021_3_OR_NEWER +using NaughtyAttributes; +using UnityEngine; + +namespace NaughtyAttributes.Test +{ + public class TypedDropdownTest : MonoBehaviour + { + [SerializeReference] + [TypeDropdown(typeof(Animal))] + public Animal MyPet; + } + + [System.Serializable] + public class Animal + { + public string nickname = "Silly Billy"; + } + + public class Dog : Animal + { + public string Breed = "Golden Retriever"; + } + + public class Cat : Animal + { + public int lives = 9; + } +} +#endif diff --git a/Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs.meta b/Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs.meta new file mode 100644 index 00000000..272e8917 --- /dev/null +++ b/Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 04bc241ae996b6b4ba2b1eb352322849 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: