diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d43cd9..a6a00b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [2.3.2] - 2025-04-18 +### Updated +- Update SubAssetPicker drawer to display mixed values and disable picker when multiple objects with different values are selected + +### Fixed +- Fix SubAssetPicker would not work with items of serialized lists and arrays +- Fix SubAssetPicker would not search for derived classes in other assemblies than the base type's assembly +- Fix tried to show the SubAssetPicker context menu as many times as there are derived types + ## [2.3.1] - 2025-04-04 ### Fixed - Path used in CreatePrefab is now relative to project folder. diff --git a/Editor/PropertyDrawer/AttributesDrawer/SubClassPickerAttributeDrawer.cs b/Editor/PropertyDrawer/AttributesDrawer/SubClassPickerAttributeDrawer.cs deleted file mode 100644 index eecfab6..0000000 --- a/Editor/PropertyDrawer/AttributesDrawer/SubClassPickerAttributeDrawer.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using UnityEditor; -using UnityEngine; - -namespace FishingCactus.CommonCode -{ - public class SubClassPickerAttributeDrawer : MonoBehaviour - { - [CustomPropertyDrawer( typeof( SubClassPicker ) )] - public class SubClassPickerDrawer : PropertyDrawer - { - // -- FIELDS - - private const string DefaultDisplay = "Pick a type"; - - // -- METHODS - - private IEnumerable GetSubClasses( - Type base_type - ) - { - return Assembly.GetAssembly( base_type ) - .GetTypes() - .Where( type => type.IsClass && !type.IsAbstract && base_type.IsAssignableFrom( type ) ); - } - - // -- UNITY - - public override float GetPropertyHeight( - SerializedProperty property, - GUIContent label - ) - { - return EditorGUI.GetPropertyHeight( property, label ); - } - - public override void OnGUI( - Rect position, - SerializedProperty property, - GUIContent label - ) - { - Type field_type = fieldInfo.FieldType; - - string type_name = property.managedReferenceValue?.GetType().Name ?? DefaultDisplay; - - Rect drop_down_rect = position; - - drop_down_rect.x += EditorGUIUtility.labelWidth + 2; - drop_down_rect.width -= EditorGUIUtility.labelWidth + 2; - drop_down_rect.height = EditorGUIUtility.singleLineHeight; - - if( EditorGUI.DropdownButton( drop_down_rect, new( type_name ), FocusType.Keyboard ) ) - { - GenericMenu menu = new GenericMenu(); - menu.AddItem( new GUIContent( "None" ), property.managedReferenceValue == null, () => - { - property.managedReferenceValue = null; - property.serializedObject.ApplyModifiedProperties(); - } ); - - foreach( Type type in GetSubClasses( field_type ) ) - { - menu.AddItem( new GUIContent( type.Name ), type_name == type.Name, () => - { - property.managedReferenceValue = type.GetConstructor( Type.EmptyTypes ).Invoke( null ); - property.serializedObject.ApplyModifiedProperties(); - } ); - - menu.ShowAsContext(); - } - } - - EditorGUI.PropertyField( position, property, label, true ); - } - } - } -} \ No newline at end of file diff --git a/Editor/PropertyDrawer/AttributesDrawer/SubClassPickerDrawer.cs b/Editor/PropertyDrawer/AttributesDrawer/SubClassPickerDrawer.cs new file mode 100644 index 0000000..11f7731 --- /dev/null +++ b/Editor/PropertyDrawer/AttributesDrawer/SubClassPickerDrawer.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace FishingCactus.CommonCode +{ + [CustomPropertyDrawer( typeof( SubClassPicker ) )] + public class SubClassPickerDrawer : PropertyDrawer + { + private const string DefaultDisplay = "Pick a type"; + + private IEnumerable GetSubClasses( + Type base_type + ) + { + if( ReflectionUtils.IsCollectionType( base_type ) + && !ReflectionUtils.TryGetEnumerableElementType( base_type, out base_type ) + ) + { + return Enumerable.Empty(); + } + + return TypeCache.GetTypesDerivedFrom( base_type ) + .Where( type => type.IsClass && !type.IsAbstract ); + } + + public override float GetPropertyHeight( + SerializedProperty property, + GUIContent label + ) + { + return EditorGUI.GetPropertyHeight( property, label ); + } + + public override void OnGUI( + Rect position, + SerializedProperty property, + GUIContent label + ) + { + Type field_type = fieldInfo.FieldType; + + string type_name = property.managedReferenceValue?.GetType().Name ?? DefaultDisplay; + + Rect drop_down_rect = position; + + drop_down_rect.x += EditorGUIUtility.labelWidth + 2; + drop_down_rect.width -= EditorGUIUtility.labelWidth + 2; + drop_down_rect.height = EditorGUIUtility.singleLineHeight; + + bool previous_show_mixed_values = EditorGUI.showMixedValue; + EditorGUI.showMixedValue = property.hasMultipleDifferentValues; + + using( new EditorGUI.DisabledGroupScope( property.hasMultipleDifferentValues ) ) + { + if( EditorGUI.DropdownButton( drop_down_rect, new( type_name ), FocusType.Keyboard ) ) + { + GenericMenu menu = new GenericMenu(); + menu.AddItem( new GUIContent( "None" ), property.managedReferenceValue == null, () => + { + property.managedReferenceValue = null; + property.serializedObject.ApplyModifiedProperties(); + } ); + + foreach( Type type in GetSubClasses( field_type ) ) + { + menu.AddItem( new GUIContent( type.Name ), type_name == type.Name, () => + { + property.managedReferenceValue = type.GetConstructor( Type.EmptyTypes ).Invoke( null ); + property.serializedObject.ApplyModifiedProperties(); + } ); + } + + menu.ShowAsContext(); + } + } + + EditorGUI.PropertyField( position, property, label, true ); + + EditorGUI.showMixedValue = previous_show_mixed_values; + } + } +} \ No newline at end of file diff --git a/Editor/PropertyDrawer/AttributesDrawer/SubClassPickerAttributeDrawer.cs.meta b/Editor/PropertyDrawer/AttributesDrawer/SubClassPickerDrawer.cs.meta similarity index 100% rename from Editor/PropertyDrawer/AttributesDrawer/SubClassPickerAttributeDrawer.cs.meta rename to Editor/PropertyDrawer/AttributesDrawer/SubClassPickerDrawer.cs.meta diff --git a/Runtime/Utilities/ReflectionUtils.cs b/Runtime/Utilities/ReflectionUtils.cs index 7c33f3e..f6396f3 100644 --- a/Runtime/Utilities/ReflectionUtils.cs +++ b/Runtime/Utilities/ReflectionUtils.cs @@ -41,6 +41,14 @@ out Type element_type return false; } + public static bool IsCollectionType( + Type list_type + ) + { + return list_type.IsArray + || ( list_type.IsGenericType && IsAssignableToGenericType( list_type, typeof( IEnumerable<> ) ) ); + } + public static bool IsAssignableToGenericType( Type type, Type generic_type diff --git a/package.json b/package.json index ef2ae7d..932232e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.fishingcactus.common-code", - "version": "2.3.1", + "version": "2.3.2", "displayName": "FC - Common Code", "description": "Code, Extensions and extra features for Fishing Cactus Games.", "unity": "2020.3",