1- using System ;
2- using System . Collections ;
1+ using System . Collections ;
32
43using UnityEditor ;
54using UnityEngine ;
@@ -9,30 +8,19 @@ namespace Toolbox.Editor.Drawers
98 [ CustomPropertyDrawer ( typeof ( PresetAttribute ) ) ]
109 public class PresetAttributeDrawer : PropertyDrawerBase
1110 {
12- protected override float GetPropertyHeightSafe ( SerializedProperty property , GUIContent label )
11+ private IList GetPresetList ( object parentObject , string sourceHandle , SerializedProperty property )
1312 {
14- return base . GetPropertyHeightSafe ( property , label ) ;
15- }
16-
17- protected override void OnGUISafe ( Rect position , SerializedProperty property , GUIContent label )
18- {
19- //NOTE: this implementation does not support multiple different sources
20- var sourceHandle = Attribute . SourceHandle ;
21- var declaringObject = property . GetDeclaringObject ( ) ;
22- //extract (if available) the real preset value
23- if ( ! ValueExtractionHelper . TryGetValue ( sourceHandle , declaringObject , out var sourceValue ) )
13+ if ( ! ValueExtractionHelper . TryGetValue ( sourceHandle , parentObject , out var sourceValue ) )
2414 {
2515 ToolboxEditorLog . MemberNotFoundWarning ( attribute , property , sourceHandle ) ;
26- EditorGUI . PropertyField ( position , property , label ) ;
27- return ;
16+ return null ;
2817 }
2918
3019 if ( ! ( sourceValue is IList presetList ) )
3120 {
3221 ToolboxEditorLog . AttributeUsageWarning ( attribute , property ,
33- string . Format ( "Preset ({0}) has to be a one-dimensional collection (array or list)." , sourceHandle ) ) ;
34- EditorGUI . PropertyField ( position , property , label ) ;
35- return ;
22+ string . Format ( "Values preset ({0}) has to be a one-dimensional collection (array or list)." , sourceHandle ) ) ;
23+ return null ;
3624 }
3725
3826 var sourceType = sourceValue . GetType ( ) ;
@@ -44,36 +32,96 @@ protected override void OnGUISafe(Rect position, SerializedProperty property, GU
4432 {
4533 ToolboxEditorLog . AttributeUsageWarning ( attribute , property ,
4634 "Type mismatch between serialized property and given Preset." ) ;
47- EditorGUI . PropertyField ( position , property , label ) ;
48- return ;
35+ return null ;
4936 }
5037
38+ return presetList ;
39+ }
40+
41+ private string [ ] GetOptions ( IList presetList )
42+ {
5143 var itemsCount = presetList . Count ;
52- var objects = new object [ itemsCount ] ;
5344 var options = new string [ itemsCount ] ;
5445 for ( var i = 0 ; i < itemsCount ; i ++ )
5546 {
56- objects [ i ] = presetList [ i ] ;
5747 options [ i ] = presetList [ i ] ? . ToString ( ) ;
5848 }
5949
60- var value = property . GetProperValue ( fieldInfo , declaringObject ) ;
61- var index = Array . IndexOf ( objects , value ) ;
50+ return options ;
51+ }
52+
53+ private string [ ] GetOptions ( IList presetList , object parentObject , string optionHandle , SerializedProperty property )
54+ {
55+ if ( string . IsNullOrEmpty ( optionHandle ) )
56+ {
57+ return GetOptions ( presetList ) ;
58+ }
59+
60+ if ( ! ValueExtractionHelper . TryGetValue ( optionHandle , parentObject , out var optionValue ) )
61+ {
62+ ToolboxEditorLog . MemberNotFoundWarning ( attribute , property , optionHandle ) ;
63+ return GetOptions ( presetList ) ;
64+ }
65+
66+ if ( ! ( optionValue is IList optionList ) )
67+ {
68+ ToolboxEditorLog . AttributeUsageWarning ( attribute , property ,
69+ string . Format ( "Options preset ({0}) has to be a one-dimensional collection (array or list)." , optionHandle ) ) ;
70+ return GetOptions ( presetList ) ;
71+ }
72+
73+ var presetsCount = presetList . Count ;
74+ var optionsCount = optionList . Count ;
75+ var options = new string [ presetsCount ] ;
76+ for ( int i = 0 ; i < presetsCount ; i ++ )
77+ {
78+ options [ i ] = i < optionsCount
79+ ? optionList [ i ] ? . ToString ( )
80+ : presetList [ i ] ? . ToString ( ) ;
81+ }
82+
83+ return options ;
84+ }
85+
86+
87+ protected override float GetPropertyHeightSafe ( SerializedProperty property , GUIContent label )
88+ {
89+ return base . GetPropertyHeightSafe ( property , label ) ;
90+ }
91+
92+ protected override void OnGUISafe ( Rect position , SerializedProperty property , GUIContent label )
93+ {
94+ //NOTE: this implementation does not support multiple different sources
95+ var sourceHandle = Attribute . SourceHandle ;
96+ var optionHandle = Attribute . OptionHandle ;
97+ var parentObject = property . GetDeclaringObject ( ) ;
98+ var presetList = GetPresetList ( parentObject , sourceHandle , property ) ;
99+ if ( presetList == null )
100+ {
101+ EditorGUI . PropertyField ( position , property , label ) ;
102+ return ;
103+ }
104+
105+ var options = GetOptions ( presetList , parentObject , optionHandle , property ) ;
106+
107+ var value = property . GetProperValue ( fieldInfo , parentObject ) ;
108+ var index = presetList . IndexOf ( value ) ;
62109
63110 //begin the true property
64111 label = EditorGUI . BeginProperty ( position , label , property ) ;
65112 EditorGUI . BeginChangeCheck ( ) ;
113+
66114 //get selected preset value
67115 index = EditorGUI . Popup ( position , label , index , EditorGUIUtility . TrTempContent ( options ) ) ;
68- index = Mathf . Clamp ( index , 0 , itemsCount - 1 ) ;
116+ index = Mathf . Clamp ( index , 0 , presetList . Count - 1 ) ;
69117 if ( EditorGUI . EndChangeCheck ( ) )
70118 {
71119 //udpate property value using previously cached FieldInfo and picked value
72120 //there is no cleaner way to do it, since we don't really know what kind of
73121 //serialized property we are updating
74122
75123 property . serializedObject . Update ( ) ;
76- property . SetProperValue ( fieldInfo , objects [ index ] ) ;
124+ property . SetProperValue ( fieldInfo , presetList [ index ] ) ;
77125 property . serializedObject . ApplyModifiedProperties ( ) ;
78126 //handle situation when updating multiple different targets
79127 property . serializedObject . SetIsDifferentCacheDirty ( ) ;
@@ -85,10 +133,10 @@ protected override void OnGUISafe(Rect position, SerializedProperty property, GU
85133
86134 public override bool IsPropertyValid ( SerializedProperty property )
87135 {
88- var declaringObject = property . GetDeclaringObject ( ) ;
136+ var parentObject = property . GetDeclaringObject ( ) ;
89137 //NOTE: reflection won't work properly on nested structs because of boxing
90138 //TODO: handle this case
91- return ! declaringObject . GetType ( ) . IsValueType ;
139+ return ! parentObject . GetType ( ) . IsValueType ;
92140 }
93141
94142
0 commit comments