using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.Rendering; namespace UnityEditor.Rendering { /// /// Builtin Drawer for Value Debug Items. /// [DebugUIDrawer(typeof(DebugUI.Value))] public sealed class DebugUIDrawerValue : DebugUIWidgetDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The widget protected override void DoGUI(Rect rect, GUIContent label, DebugUI.Value field) { EditorGUI.LabelField(rect, label, EditorGUIUtility.TrTextContent(field.FormatString(field.GetValue()))); } } /// /// Builtin Drawer for ValueTuple Debug Items. /// [DebugUIDrawer(typeof(DebugUI.ValueTuple))] public sealed class DebugUIDrawerValueTuple : DebugUIWidgetDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The widget protected override void DoGUI(Rect rect, GUIContent label, DebugUI.ValueTuple field) { EditorGUI.PrefixLabel(rect, label); // Following layout should match DebugUIDrawerFoldout to make column labels align Rect drawRect = GUILayoutUtility.GetLastRect(); int indent = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; //be at left of rects for (int i = 0; i < field.numElements; i++) { var columnRect = drawRect; columnRect.x += EditorGUIUtility.labelWidth + i * DebugWindow.Styles.foldoutColumnWidth; columnRect.width = DebugWindow.Styles.foldoutColumnWidth; var value = field.values[i].GetValue(); var style = EditorStyles.label; if (Convert.ToSingle(value) == 0) style = DebugWindow.Styles.labelWithZeroValueStyle; EditorGUI.LabelField(columnRect, field.values[i].FormatString(value), style); } EditorGUI.indentLevel = indent; } } /// /// Builtin Drawer for ProgressBarValue Debug Items. /// [DebugUIDrawer(typeof(DebugUI.ProgressBarValue))] public sealed class DebugUIDrawerProgressBarValue : DebugUIWidgetDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The widget protected override void DoGUI(Rect rect, GUIContent label, DebugUI.ProgressBarValue field) { var progressBarRect = EditorGUI.PrefixLabel(rect, label); float value = (float)field.GetValue(); EditorGUI.ProgressBar(progressBarRect, value, field.FormatString(value)); } } /// /// Builtin Drawer for Button Debug Items. /// [DebugUIDrawer(typeof(DebugUI.Button))] public sealed class DebugUIDrawerButton : DebugUIWidgetDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The widget protected override void DoGUI(Rect rect, GUIContent label, DebugUI.Button field) { rect = EditorGUI.IndentedRect(rect); if (GUI.Button(rect, label, EditorStyles.miniButton)) { if (field.action != null) field.action(); } } } /// /// Builtin Drawer for Boolean Debug Items. /// [DebugUIDrawer(typeof(DebugUI.BoolField))] public sealed class DebugUIDrawerBoolField : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The value protected override bool DoGUI(Rect rect, GUIContent label, DebugUI.BoolField field, DebugStateBool state) { return EditorGUI.Toggle(rect, label, field.GetValue()); } } /// /// Builtin Drawer for History Boolean Debug Items. /// [DebugUIDrawer(typeof(DebugUI.HistoryBoolField))] public sealed class DebugUIDrawerHistoryBoolField : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override bool DoGUI(Rect rect, GUIContent label, DebugUI.HistoryBoolField field, DebugStateBool state) { var labelRect = rect; labelRect.width = EditorGUIUtility.labelWidth; const int oneValueWidth = 70; var valueRects = new Rect[field.historyDepth + 1]; for (int i = 0; i < field.historyDepth + 1; i++) { valueRects[i] = rect; valueRects[i].x += EditorGUIUtility.labelWidth + i * oneValueWidth; valueRects[i].width = oneValueWidth; } EditorGUI.LabelField(labelRect, label); int indent = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; //be at left of rects bool value = EditorGUI.Toggle(valueRects[0], field.GetValue()); using (new EditorGUI.DisabledScope(true)) { for (int i = 0; i < field.historyDepth; i++) EditorGUI.Toggle(valueRects[i + 1], field.GetHistoryValue(i)); } EditorGUI.indentLevel = indent; return value; } } /// /// Builtin Drawer for Integer Debug Items. /// [DebugUIDrawer(typeof(DebugUI.IntField))] public sealed class DebugUIDrawerIntField : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override int DoGUI(Rect rect, GUIContent label, DebugUI.IntField field, DebugStateInt state) { return field.min != null && field.max != null ? EditorGUI.IntSlider(rect, label, field.GetValue(), field.min(), field.max()) : EditorGUI.IntField(rect, label, field.GetValue()); } } /// /// Builtin Drawer for Unsigned Integer Debug Items. /// [DebugUIDrawer(typeof(DebugUI.UIntField))] public sealed class DebugUIDrawerUIntField : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override uint DoGUI(Rect rect, GUIContent label, DebugUI.UIntField field, DebugStateUInt state) { // No UIntField so we need to max to 0 ourselves or the value will wrap around int tmp = field.min != null && field.max != null ? EditorGUI.IntSlider(rect, label, Mathf.Max(0, (int)field.GetValue()), Mathf.Max(0, (int)field.min()), Mathf.Max(0, (int)field.max())) : EditorGUI.IntField(rect, label, Mathf.Max(0, (int)field.GetValue())); return (uint)Mathf.Max(0, tmp); } } /// /// Builtin Drawer for Float Debug Items. /// [DebugUIDrawer(typeof(DebugUI.FloatField))] public sealed class DebugUIDrawerFloatField : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override float DoGUI(Rect rect, GUIContent label, DebugUI.FloatField field, DebugStateFloat state) { return field.min != null && field.max != null ? EditorGUI.Slider(rect, label, field.GetValue(), field.min(), field.max()) : EditorGUI.FloatField(rect, label, field.GetValue()); } } /// /// Builtin Drawer for Enum Debug Items. /// [DebugUIDrawer(typeof(DebugUI.EnumField))] public sealed class DebugUIDrawerEnumField : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override int DoGUI(Rect rect, GUIContent label, DebugUI.EnumField field, DebugStateEnum state) { int index = Mathf.Max(0, field.currentIndex); // Fallback just in case, we may be handling sub/sectioned enums here int value = field.GetValue(); if (field.enumNames == null || field.enumValues == null) { EditorGUI.LabelField(rect, label, "Can't draw an empty enumeration."); } else if (field.enumNames.Length != field.enumValues.Length) { EditorGUI.LabelField(rect, label, "Invalid data"); } else { index = EditorGUI.IntPopup(rect, label, index, field.enumNames, field.indexes); value = field.enumValues[index]; } return value; } } /// /// Builtin Drawer for Object Popup Fields Items. /// [DebugUIDrawer(typeof(DebugUI.ObjectPopupField))] public sealed class DebugUIDrawerObjectPopupField : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override UnityEngine.Object DoGUI(Rect rect, GUIContent label, DebugUI.ObjectPopupField field, DebugStateObject state) { var selectedValue = field.GetValue(); rect = EditorGUI.PrefixLabel(rect, label); var elements = field.getObjects(); if (elements?.Any() ?? false) { var elementsArrayNames = elements.Select(e => e.name).ToArray(); var elementsArrayIndices = Enumerable.Range(0, elementsArrayNames.Length).ToArray(); var selectedIndex = selectedValue != null ? Array.IndexOf(elementsArrayNames, selectedValue.name) : 0; var newSelectedIndex = EditorGUI.IntPopup(rect, selectedIndex, elementsArrayNames, elementsArrayIndices); if (selectedIndex != newSelectedIndex) selectedValue = elements.ElementAt(newSelectedIndex); } else { EditorGUI.LabelField(rect, "Can't draw an empty enumeration."); } return selectedValue; } } /// /// Builtin Drawer for History Enum Debug Items. /// [DebugUIDrawer(typeof(DebugUI.HistoryEnumField))] public sealed class DebugUIDrawerHistoryEnumField : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override int DoGUI(Rect rect, GUIContent label, DebugUI.HistoryEnumField field, DebugStateEnum state) { int index = -1; int value = field.GetValue(); if (field.enumNames == null || field.enumValues == null) { EditorGUILayout.LabelField("Can't draw an empty enumeration."); } else { index = field.currentIndex; // Fallback just in case, we may be handling sub/sectionned enums here if (index < 0) index = 0; var labelRect = rect; labelRect.width = EditorGUIUtility.labelWidth; const int oneValueWidth = 70; var valueRects = new Rect[field.historyDepth + 1]; for (int i = 0; i < field.historyDepth + 1; i++) { valueRects[i] = rect; valueRects[i].x += EditorGUIUtility.labelWidth + i * oneValueWidth; valueRects[i].width = oneValueWidth; } EditorGUI.LabelField(labelRect, label); int indent = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; //be at left of rects index = EditorGUI.IntPopup(valueRects[0], index, field.enumNames, field.indexes); value = field.enumValues[index]; using (new EditorGUI.DisabledScope(true)) { for (int i = 0; i < field.historyDepth; i++) EditorGUI.IntPopup(valueRects[i + 1], field.GetHistoryValue(i), field.enumNames, field.indexes); } EditorGUI.indentLevel = indent; value = field.enumValues[index]; } return value; } } /// /// Builtin Drawer for Bitfield Debug Items. /// [DebugUIDrawer(typeof(DebugUI.BitField))] public sealed class DebugUIDrawerBitField : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override Enum DoGUI(Rect rect, GUIContent label, DebugUI.BitField field, DebugStateFlags state) { Enum value = field.GetValue(); // Skip first element (with value 0) because EditorGUI.MaskField adds a 'Nothing' field anyway var enumNames = new string[field.enumNames.Length - 1]; for (int i = 0; i < enumNames.Length; i++) enumNames[i] = field.enumNames[i + 1].text; var index = EditorGUI.MaskField(rect, label, (int)Convert.ToInt32(value), enumNames); value = Enum.Parse(value.GetType(), index.ToString()) as Enum; return value; } } /// /// Builtin Drawer for Maskfield Debug Items. /// [DebugUIDrawer(typeof(DebugUI.MaskField))] public sealed class DebugUIDrawerMaskField : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override uint DoGUI(Rect rect, GUIContent label, DebugUI.MaskField field, DebugStateUInt state) { uint value = field.GetValue(); var enumNames = new string[field.enumNames.Length]; for (int i = 0; i < enumNames.Length; i++) enumNames[i] = field.enumNames[i].text; var mask = EditorGUI.MaskField(rect, label, (int)value, enumNames); return (uint)mask; } } /// /// Builtin Drawer for Foldout Debug Items. /// [DebugUIDrawer(typeof(DebugUI.Foldout))] public sealed class DebugUIDrawerFoldout : DebugUIDrawer { const int k_HeaderVerticalMargin = 2; static void DisplayColumns(Rect drawRect, List rowContents) { drawRect.x += EditorGUIUtility.labelWidth; drawRect.width = DebugWindow.Styles.foldoutColumnWidth; int indent = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; //be at left of rects for (int i = 0; i < rowContents.Count; i++) { EditorGUI.LabelField(drawRect, rowContents[i], EditorStyles.miniBoldLabel); // Offset the rect to the next possible column drawRect.x += DebugWindow.Styles.foldoutColumnWidth; } EditorGUI.indentLevel = indent; } /// /// Implement this to execute processing before UI rendering. /// /// Widget that is going to be rendered. /// Debug State associated with the Debug Item. public override void Begin(DebugUI.Widget widget, DebugState state) { var w = Cast(widget); var s = Cast(state); var title = EditorGUIUtility.TrTextContent(w.displayName, w.tooltip); Action fillContextMenuAction = null; if (w.contextMenuItems != null) { fillContextMenuAction = menu => { foreach (var item in w.contextMenuItems) { menu.AddItem(EditorGUIUtility.TrTextContent(item.displayName), false, () => item.action.Invoke()); } }; } bool previousValue = (bool)w.GetValue(); bool value = CoreEditorUtils.DrawHeaderFoldout(title, previousValue, isTitleHeader: w.isHeader, customMenuContextAction: fillContextMenuAction); if (previousValue != value) Apply(w, s, value); EditorGUI.indentLevel++; } /// /// OnGUI implementation for Foldout DebugUIDrawer. /// /// DebugUI Widget. /// Debug State associated with the Debug Item. /// The state of the widget. public override bool OnGUI(DebugUI.Widget widget, DebugState state) { var w = Cast(widget); if (w.opened && w.columnLabels != null) { var drawRect = PrepareControlRect(EditorGUIUtility.singleLineHeight); drawRect.x = 0; DisplayColumns(drawRect, w.rowContents); } return w.opened; } /// /// End implementation for Foldout DebugUIDrawer. /// /// DebugUI Widget. /// Debug State associated with the Debug Item. public override void End(DebugUI.Widget widget, DebugState state) { EditorGUI.indentLevel--; var w = Cast(widget); if (w.isHeader) GUILayout.Space(k_HeaderVerticalMargin); } } /// /// Builtin Drawer for Color Debug Items. /// [DebugUIDrawer(typeof(DebugUI.ColorField))] public sealed class DebugUIDrawerColorField : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override Color DoGUI(Rect rect, GUIContent label, DebugUI.ColorField field, DebugStateColor state) { return EditorGUI.ColorField(rect, label, field.GetValue(), field.showPicker, field.showAlpha, field.hdr); } } /// /// Builtin Drawer for Vector2 Debug Items. /// [DebugUIDrawer(typeof(DebugUI.Vector2Field))] public sealed class DebugUIDrawerVector2Field : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override Vector2 DoGUI(Rect rect, GUIContent label, DebugUI.Vector2Field field, DebugStateVector2 state) { return EditorGUILayout.Vector2Field(label, field.GetValue()); } } /// /// Builtin Drawer for Vector3 Debug Items. /// [DebugUIDrawer(typeof(DebugUI.Vector3Field))] public sealed class DebugUIDrawerVector3Field : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override Vector3 DoGUI(Rect rect, GUIContent label, DebugUI.Vector3Field field, DebugStateVector3 state) { return EditorGUILayout.Vector3Field(label, field.GetValue()); } } /// /// Builtin Drawer for Vector4 Debug Items. /// [DebugUIDrawer(typeof(DebugUI.Vector4Field))] public sealed class DebugUIDrawerVector4Field : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override Vector4 DoGUI(Rect rect, GUIContent label, DebugUI.Vector4Field field, DebugStateVector4 state) { return EditorGUILayout.Vector4Field(label, field.GetValue()); } } /// /// Builtin Drawer for items. /// [DebugUIDrawer(typeof(DebugUI.ObjectField))] public sealed class DebugUIDrawerObjectField : DebugUIFieldDrawer { /// /// Does the field of the given type /// /// The rect to draw the field /// The label for the field /// The field /// The state /// The current value from the UI protected override UnityEngine.Object DoGUI(Rect rect, GUIContent label, DebugUI.ObjectField field, DebugStateObject state) { return EditorGUI.ObjectField(rect, label, field.GetValue(), field.type, true); } } /// /// Builtin Drawer for Items. /// [DebugUIDrawer(typeof(DebugUI.ObjectListField))] public sealed class DebugUIDrawerObjectListField : DebugUIDrawer { /// /// Implement this to execute UI rendering. /// /// Widget that is going to be rendered. /// Debug State associated with the Debug Item. /// Returns the state of the widget. public override bool OnGUI(DebugUI.Widget widget, DebugState state) { var w = Cast(widget); var objects = w.GetValue(); float height = Math.Max(objects != null ? objects.Length : 0, 1) * DebugWindow.Styles.singleRowHeight; var rect = PrepareControlRect(height); rect = EditorGUI.PrefixLabel(rect, EditorGUIUtility.TrTextContent(widget.displayName)); EditorGUI.BeginChangeCheck(); DoObjectList(rect, w, objects); if (EditorGUI.EndChangeCheck()) Apply(w, state, objects); return true; } internal static void DoObjectList(Rect rect, DebugUI.ObjectListField widget, UnityEngine.Object[] objects) { if (objects == null || objects.Length == 0) { EditorGUI.LabelField(rect, GUIContent.none, EditorGUIUtility.TrTextContent("Empty")); return; } rect.height = EditorGUIUtility.singleLineHeight; for (int i = 0; i < objects.Length; i++) { objects[i] = EditorGUI.ObjectField(rect, GUIContent.none, objects[i], widget.type, true); rect.y += DebugWindow.Styles.singleRowHeight; } } } /// /// Builtin Drawer for MessageBox Items. /// [DebugUIDrawer(typeof(DebugUI.MessageBox))] public sealed class DebugUIDrawerMessageBox : DebugUIDrawer { /// /// Implement this to execute UI rendering. /// /// Widget that is going to be rendered. /// Debug State associated with the Debug Item. /// Returns the state of the widget. public override bool OnGUI(DebugUI.Widget widget, DebugState state) { var w = Cast(widget); var type = w.style switch { DebugUI.MessageBox.Style.Info => MessageType.Info, DebugUI.MessageBox.Style.Warning => MessageType.Warning, DebugUI.MessageBox.Style.Error => MessageType.Error, _ => MessageType.None }; EditorGUILayout.HelpBox(w.message, type); return true; } } /// /// Builtin Drawer for Container Debug Items. /// [DebugUIDrawer(typeof(DebugUI.Container))] public sealed class DebugUIDrawerContainer : DebugUIDrawer { /// /// Implement this to execute processing before UI rendering. /// /// Widget that is going to be rendered. /// Debug State associated with the Debug Item. public override void Begin(DebugUI.Widget widget, DebugState state) { var w = Cast(widget); if (!w.hideDisplayName) EditorGUILayout.LabelField(EditorGUIUtility.TrTextContent(widget.displayName, widget.tooltip), EditorStyles.boldLabel); EditorGUI.indentLevel++; } /// /// Implement this to execute processing after UI rendering. /// /// Widget that is going to be rendered. /// Debug State associated with the Debug Item. public override void End(DebugUI.Widget widget, DebugState state) { EditorGUI.indentLevel--; } } /// /// Builtin Drawer for Horizontal Box Debug Items. /// [DebugUIDrawer(typeof(DebugUI.HBox))] public sealed class DebugUIDrawerHBox : DebugUIDrawer { /// /// Implement this to execute processing before UI rendering. /// /// Widget that is going to be rendered. /// Debug State associated with the Debug Item. public override void Begin(DebugUI.Widget widget, DebugState state) { EditorGUILayout.BeginHorizontal(); } /// /// Implement this to execute processing after UI rendering. /// /// Widget that is going to be rendered. /// Debug State associated with the Debug Item. public override void End(DebugUI.Widget widget, DebugState state) { EditorGUILayout.EndHorizontal(); } } /// /// Builtin Drawer for Vertical Box Debug Items. /// [DebugUIDrawer(typeof(DebugUI.VBox))] public sealed class DebugUIDrawerVBox : DebugUIDrawer { /// /// Implement this to execute processing before UI rendering. /// /// Widget that is going to be rendered. /// Debug State associated with the Debug Item. public override void Begin(DebugUI.Widget widget, DebugState state) { EditorGUILayout.BeginVertical(); } /// /// Implement this to execute processing after UI rendering. /// /// Widget that is going to be rendered. /// Debug State associated with the Debug Item. public override void End(DebugUI.Widget widget, DebugState state) { EditorGUILayout.EndVertical(); } } /// /// Builtin Drawer for Table Debug Items. /// [DebugUIDrawer(typeof(DebugUI.Table))] public sealed class DebugUIDrawerTable : DebugUIDrawer { /// /// Implement this to execute UI rendering. /// /// Widget that is going to be rendered. /// Debug State associated with the Debug Item. /// Returns the state of the widget. public override bool OnGUI(DebugUI.Widget widget, DebugState state) { const float k_ScrollBarHeight = 15; var w = Cast(widget); var header = w.Header; var visible = header.state.visibleColumns; float contentHeight = 0.0f; foreach (DebugUI.Table.Row row in w.children) contentHeight += row != null ? GetRowHeight(row, visible) : EditorGUIUtility.singleLineHeight; // Put some space before the array PrepareControlRect(EditorGUIUtility.singleLineHeight * 0.5f); // Draw an outline around the table var rect = EditorGUI.IndentedRect(PrepareControlRect(header.height + contentHeight + k_ScrollBarHeight)); rect = DrawOutline(rect); // Compute rects var headerRect = new Rect(rect.x, rect.y, rect.width, header.height); var contentRect = new Rect(rect.x, headerRect.yMax, rect.width, rect.height - headerRect.height); var viewRect = new Rect(contentRect.x, contentRect.y, header.state.widthOfAllVisibleColumns, contentRect.height); var rowRect = contentRect; viewRect.height -= k_ScrollBarHeight; // Show header header.OnGUI(headerRect, Mathf.Max(w.scroll.x, 0f)); // Show array content w.scroll = GUI.BeginScrollView(contentRect, w.scroll, viewRect); { var columns = header.state.columns; for (int r = 0; r < w.children.Count; r++) { var row = Cast(w.children[r]); rowRect.x = contentRect.x; rowRect.width = columns[0].width; rowRect.height = (row is DebugUI.Table.Row tableRow) ? GetRowHeight(tableRow, visible) : EditorGUIUtility.singleLineHeight; rowRect.xMin += 2; rowRect.xMax -= 2; bool isAlternate = r % 2 == 0; EditorGUI.LabelField(rowRect, GUIContent.none, EditorGUIUtility.TrTextContent(row.displayName),isAlternate ? DebugWindow.Styles.centeredLeft : DebugWindow.Styles.centeredLeftAlternate); rowRect.xMin -= 2; rowRect.xMax += 2; using (new EditorGUI.DisabledScope(w.isReadOnly)) { for (int c = 1; c < visible.Length; c++) { rowRect.x += rowRect.width; rowRect.width = columns[visible[c]].width; if (!row.isHidden) DisplayChild(rowRect, row.children[visible[c] - 1], isAlternate); } rowRect.y += rowRect.height; } } } GUI.EndScrollView(false); return false; } internal float GetRowHeight(DebugUI.Table.Row row, int[] visibleColumns) { float height = EditorGUIUtility.singleLineHeight; for (int c = 1; c < visibleColumns.Length; c++) { var child = row.children[visibleColumns[c] - 1] as DebugUI.ObjectListField; if (child == null || child.GetValue() == null) continue; height = Mathf.Max(height, child.GetValue().Length * DebugWindow.Styles.singleRowHeight); } return height; } internal Rect DrawOutline(Rect rect) { if (Event.current.type != EventType.Repaint) return rect; float size = 1.0f; var color = EditorGUIUtility.isProSkin ? new Color(0.12f, 0.12f, 0.12f, 1.333f) : new Color(0.6f, 0.6f, 0.6f, 1.333f); Color orgColor = GUI.color; GUI.color = GUI.color * color; GUI.DrawTexture(new Rect(rect.x, rect.y, rect.width, size), EditorGUIUtility.whiteTexture); GUI.DrawTexture(new Rect(rect.x, rect.yMax - size, rect.width, size), EditorGUIUtility.whiteTexture); GUI.DrawTexture(new Rect(rect.x, rect.y + 1, size, rect.height - 2 * size), EditorGUIUtility.whiteTexture); GUI.DrawTexture(new Rect(rect.xMax - size, rect.y + 1, size, rect.height - 2 * size), EditorGUIUtility.whiteTexture); GUI.color = orgColor; return new Rect(rect.x + size, rect.y + size, rect.width - 2 * size, rect.height - 2 * size); } internal void DisplayChild(Rect rect, DebugUI.Widget child, bool isAlternate) { rect.xMin += 2; rect.xMax -= 2; if (child.isHidden) { EditorGUI.LabelField(rect, "-"); } else { if (child.GetType() == typeof(DebugUI.Value)) { var widget = Cast(child); EditorGUI.LabelField(rect, GUIContent.none, EditorGUIUtility.TrTextContent(widget.GetValue().ToString()), isAlternate ? DebugWindow.Styles.centeredLeft : DebugWindow.Styles.centeredLeftAlternate); } else if (child.GetType() == typeof(DebugUI.ColorField)) { var widget = Cast(child); EditorGUI.ColorField(rect, GUIContent.none, widget.GetValue(), false, widget.showAlpha, widget.hdr); } else if (child.GetType() == typeof(DebugUI.BoolField)) { var widget = Cast(child); EditorGUI.Toggle(rect, GUIContent.none, widget.GetValue()); } else if (child.GetType() == typeof(DebugUI.ObjectField)) { var widget = Cast(child); EditorGUI.ObjectField(rect, GUIContent.none, widget.GetValue(), widget.type, true); } else if (child.GetType() == typeof(DebugUI.ObjectListField)) { var widget = Cast(child); DebugUIDrawerObjectListField.DoObjectList(rect, widget, widget.GetValue()); } } } } }