@@ -89,9 +89,152 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten
8989 if ( attribute is DoNotNormalizeAttribute && string . IsNullOrEmpty ( label . tooltip ) )
9090 label . tooltip = Content . doNotNormalizeTooltip ;
9191
92- EditorGUI . BeginProperty ( position , label , property ) ;
93- EditorGUI . MultiPropertyField ( position , subLabels , property . FindPropertyRelative ( startIter ) , label ) ;
92+ label = EditorGUI . BeginProperty ( position , label , property ) ;
93+ var valuesIterator = property . FindPropertyRelative ( startIter ) ;
94+ MultiPropertyField ( position , subLabels , valuesIterator , label ) ;
9495 EditorGUI . EndProperty ( ) ;
9596 }
97+
98+ void MultiPropertyField ( Rect position , GUIContent [ ] subLabels , SerializedProperty valuesIterator , GUIContent label )
99+ {
100+ #if UNITY_2022_1_OR_NEWER
101+ EditorGUI . MultiPropertyField ( position , subLabels , valuesIterator , label , EditorGUI . PropertyVisibility . All ) ;
102+ #else
103+ EditorGUICopy . MultiPropertyField ( position , subLabels , valuesIterator , label ) ;
104+ #endif
105+ }
106+ }
107+
108+ #if ! UNITY_2022_1_OR_NEWER
109+ internal class EditorGUICopy
110+ {
111+ internal const float kSpacingSubLabel = 4 ;
112+ private const float kIndentPerLevel = 15 ;
113+ internal const float kPrefixPaddingRight = 2 ;
114+ internal static int indentLevel = 0 ;
115+ private static readonly int s_FoldoutHash = "Foldout" . GetHashCode ( ) ;
116+
117+ // internal static readonly SVC<float> kVerticalSpacingMultiField = new SVC<float>("--theme-multifield-vertical-spacing", 0.0f);
118+ // kVerticalSpacingMultiField should actually look like the above line ^^^ but we don't have access to SVC<T>,
119+ // so instead we just set this value to what is observed in the debugger with the Unity dark theme.
120+ internal const float kVerticalSpacingMultiField = 2 ;
121+
122+ internal enum PropertyVisibility
123+ {
124+ All ,
125+ OnlyVisible
126+ }
127+
128+ // This code is basically EditorGUI.MultiPropertyField(Rect, GUIContent[], SerializedProperty, GUIContent),
129+ // but with the property visibility assumed to be "All" instead of "OnlyVisible". We really want to have "All"
130+ // because it's possible for someone to hide something in the inspector with [HideInInspector] but then manually
131+ // draw it themselves later. In this case, if you called EditorGUI.MultiPropertyField() directly, you'd
132+ // end up with some fields that point to some unrelated visible property.
133+ public static void MultiPropertyField ( Rect position , GUIContent [ ] subLabels , SerializedProperty valuesIterator , GUIContent label )
134+ {
135+ int id = GUIUtility . GetControlID ( s_FoldoutHash , FocusType . Keyboard , position ) ;
136+ position = MultiFieldPrefixLabel ( position , id , label , subLabels . Length ) ;
137+ position . height = EditorGUIUtility . singleLineHeight ;
138+ MultiPropertyFieldInternal ( position , subLabels , valuesIterator , PropertyVisibility . All ) ;
139+ }
140+
141+ internal static void BeginDisabled ( bool disabled )
142+ {
143+ // Unused, but left here to minimize changes in EditorGUICopy.MultiPropertyFieldInternal().
144+ }
145+
146+ internal static void EndDisabled ( )
147+ {
148+ // Unused, but left here to minimize changes in EditorGUICopy.MultiPropertyFieldInternal().
149+ }
150+
151+ internal static float CalcPrefixLabelWidth ( GUIContent label , GUIStyle style = null )
152+ {
153+ if ( style == null )
154+ style = EditorStyles . label ;
155+ return style . CalcSize ( label ) . x ;
156+ }
157+
158+ internal static void MultiPropertyFieldInternal ( Rect position , GUIContent [ ] subLabels , SerializedProperty valuesIterator , PropertyVisibility visibility , bool [ ] disabledMask = null , float prefixLabelWidth = - 1 )
159+ {
160+ int eCount = subLabels . Length ;
161+ float w = ( position . width - ( eCount - 1 ) * kSpacingSubLabel ) / eCount ;
162+ Rect nr = new Rect ( position ) { width = w } ;
163+ float t = EditorGUIUtility . labelWidth ;
164+ int l = indentLevel ;
165+ indentLevel = 0 ;
166+ for ( int i = 0 ; i < subLabels . Length ; i ++ )
167+ {
168+ EditorGUIUtility . labelWidth = prefixLabelWidth > 0 ? prefixLabelWidth : CalcPrefixLabelWidth ( subLabels [ i ] ) ;
169+
170+ if ( disabledMask != null )
171+ BeginDisabled ( disabledMask [ i ] ) ;
172+ EditorGUI . PropertyField ( nr , valuesIterator , subLabels [ i ] ) ;
173+ if ( disabledMask != null )
174+ EndDisabled ( ) ;
175+ nr . x += w + kSpacingSubLabel ;
176+
177+ switch ( visibility )
178+ {
179+ case PropertyVisibility . All :
180+ valuesIterator . Next ( false ) ;
181+ break ;
182+
183+ case PropertyVisibility . OnlyVisible :
184+ valuesIterator . NextVisible ( false ) ;
185+ break ;
186+ }
187+ }
188+ EditorGUIUtility . labelWidth = t ;
189+ indentLevel = l ;
190+ }
191+
192+ internal static bool LabelHasContent ( GUIContent label )
193+ {
194+ if ( label == null )
195+ {
196+ return true ;
197+ }
198+ // @TODO: find out why checking for GUIContent.none doesn't work
199+ return label . text != string . Empty || label . image != null ;
200+ }
201+
202+ internal static float indent => indentLevel * kIndentPerLevel ;
203+
204+ internal static Rect MultiFieldPrefixLabel ( Rect totalPosition , int id , GUIContent label , int columns )
205+ {
206+ if ( ! LabelHasContent ( label ) )
207+ {
208+ return EditorGUI . IndentedRect ( totalPosition ) ;
209+ }
210+
211+ if ( EditorGUIUtility . wideMode )
212+ {
213+ Rect labelPosition = new Rect ( totalPosition . x + indent , totalPosition . y , EditorGUIUtility . labelWidth - indent , EditorGUIUtility . singleLineHeight ) ;
214+ Rect fieldPosition = totalPosition ;
215+ fieldPosition . xMin += EditorGUIUtility . labelWidth + kPrefixPaddingRight ;
216+
217+ // If there are 2 columns we use the same column widths as if there had been 3 columns
218+ // in order to make columns line up neatly.
219+ if ( columns == 2 )
220+ {
221+ float columnWidth = ( fieldPosition . width - ( 3 - 1 ) * kSpacingSubLabel ) / 3f ;
222+ fieldPosition . xMax -= ( columnWidth + kSpacingSubLabel ) ;
223+ }
224+
225+ EditorGUI . HandlePrefixLabel ( totalPosition , labelPosition , label , id ) ;
226+ return fieldPosition ;
227+ }
228+ else
229+ {
230+ Rect labelPosition = new Rect ( totalPosition . x + indent , totalPosition . y , totalPosition . width - indent , EditorGUIUtility . singleLineHeight ) ;
231+ Rect fieldPosition = totalPosition ;
232+ fieldPosition . xMin += indent + kIndentPerLevel ;
233+ fieldPosition . yMin += EditorGUIUtility . singleLineHeight + kVerticalSpacingMultiField ;
234+ EditorGUI . HandlePrefixLabel ( totalPosition , labelPosition , label , id ) ;
235+ return fieldPosition ;
236+ }
237+ }
96238 }
239+ #endif
97240}
0 commit comments