1
- using System ;
2
- using System . Collections ;
1
+ using System . Collections ;
3
2
4
3
using UnityEditor ;
5
4
using UnityEngine ;
@@ -9,30 +8,19 @@ namespace Toolbox.Editor.Drawers
9
8
[ CustomPropertyDrawer ( typeof ( PresetAttribute ) ) ]
10
9
public class PresetAttributeDrawer : PropertyDrawerBase
11
10
{
12
- protected override float GetPropertyHeightSafe ( SerializedProperty property , GUIContent label )
11
+ private IList GetPresetList ( object parentObject , string sourceHandle , SerializedProperty property )
13
12
{
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 ) )
24
14
{
25
15
ToolboxEditorLog . MemberNotFoundWarning ( attribute , property , sourceHandle ) ;
26
- EditorGUI . PropertyField ( position , property , label ) ;
27
- return ;
16
+ return null ;
28
17
}
29
18
30
19
if ( ! ( sourceValue is IList presetList ) )
31
20
{
32
21
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 ;
36
24
}
37
25
38
26
var sourceType = sourceValue . GetType ( ) ;
@@ -44,36 +32,96 @@ protected override void OnGUISafe(Rect position, SerializedProperty property, GU
44
32
{
45
33
ToolboxEditorLog . AttributeUsageWarning ( attribute , property ,
46
34
"Type mismatch between serialized property and given Preset." ) ;
47
- EditorGUI . PropertyField ( position , property , label ) ;
48
- return ;
35
+ return null ;
49
36
}
50
37
38
+ return presetList ;
39
+ }
40
+
41
+ private string [ ] GetOptions ( IList presetList )
42
+ {
51
43
var itemsCount = presetList . Count ;
52
- var objects = new object [ itemsCount ] ;
53
44
var options = new string [ itemsCount ] ;
54
45
for ( var i = 0 ; i < itemsCount ; i ++ )
55
46
{
56
- objects [ i ] = presetList [ i ] ;
57
47
options [ i ] = presetList [ i ] ? . ToString ( ) ;
58
48
}
59
49
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 ) ;
62
109
63
110
//begin the true property
64
111
label = EditorGUI . BeginProperty ( position , label , property ) ;
65
112
EditorGUI . BeginChangeCheck ( ) ;
113
+
66
114
//get selected preset value
67
115
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 ) ;
69
117
if ( EditorGUI . EndChangeCheck ( ) )
70
118
{
71
119
//udpate property value using previously cached FieldInfo and picked value
72
120
//there is no cleaner way to do it, since we don't really know what kind of
73
121
//serialized property we are updating
74
122
75
123
property . serializedObject . Update ( ) ;
76
- property . SetProperValue ( fieldInfo , objects [ index ] ) ;
124
+ property . SetProperValue ( fieldInfo , presetList [ index ] ) ;
77
125
property . serializedObject . ApplyModifiedProperties ( ) ;
78
126
//handle situation when updating multiple different targets
79
127
property . serializedObject . SetIsDifferentCacheDirty ( ) ;
@@ -85,10 +133,10 @@ protected override void OnGUISafe(Rect position, SerializedProperty property, GU
85
133
86
134
public override bool IsPropertyValid ( SerializedProperty property )
87
135
{
88
- var declaringObject = property . GetDeclaringObject ( ) ;
136
+ var parentObject = property . GetDeclaringObject ( ) ;
89
137
//NOTE: reflection won't work properly on nested structs because of boxing
90
138
//TODO: handle this case
91
- return ! declaringObject . GetType ( ) . IsValueType ;
139
+ return ! parentObject . GetType ( ) . IsValueType ;
92
140
}
93
141
94
142
0 commit comments