Skip to content

Commit 344868b

Browse files
committed
DOTS-5107: Fix vector drawing in the inspector. (#199)
Fix property drawing in the inspector when manually drawing a property that was hidden with `[HideInInspector]`.
1 parent be481e3 commit 344868b

File tree

2 files changed

+153
-2
lines changed

2 files changed

+153
-2
lines changed

src/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## [1.2.5] - 2021-11-01
4+
### Added
5+
### Changed
6+
### Deprecated
7+
### Removed
8+
### Fixed
9+
* Fixed property drawing when manually drawing a property that was hidden with [HideInInspector].
10+
311
## [1.2.4] - 2021-09-22
412
### Added
513
* Added `[Il2CppEagerStaticClassConstruction]` to Unity.Mathematics types to run static constructors at startup. This improves IL2CPP performance slightly for types that have static constructors.

src/Unity.Mathematics.Editor/PrimitiveVectorDrawer.cs

Lines changed: 145 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)