Skip to content

Commit

Permalink
Replace GUIContent-based tree lines with rect rextures; update defaul…
Browse files Browse the repository at this point in the history
…t settings
  • Loading branch information
arimger committed Aug 23, 2024
1 parent 4d53280 commit 71168a5
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 41 deletions.
60 changes: 21 additions & 39 deletions Assets/Editor Toolbox/Editor/Hierarchy/HierarchyPropertyLabel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,11 @@ public override void OnGui(Rect rect)

private class HierarchyTreeLinesLabel : HierarchyPropertyLabel, IDisposable
{
//TODO: properties to expose when switching to SerializedReference-based implementation:
// - color
// - isDashed
// - tickness

private const float firstElementWidthOffset = 4.0f;

#if UNITY_2019_1_OR_NEWER
Expand All @@ -312,6 +317,7 @@ private class HierarchyTreeLinesLabel : HierarchyPropertyLabel, IDisposable
private const float startXPosition = 0.0f;
#endif
private const float columnSize = 14.0f;
private const bool isDashed = true;

private readonly List<TreeLineLevelRenderer> levelRenderers = new List<TreeLineLevelRenderer>();

Expand Down Expand Up @@ -348,15 +354,14 @@ public sealed override void OnGui(Rect rect)
itemRenderCount++;

rect.x = startXPosition;
//we need 2x column size for full-line cases when object has no children and there is no foldout
rect.width = 2 * columnSize + firstElementWidthOffset;
rect.width = columnSize + firstElementWidthOffset;

var targetTransform = target.transform;
var siblingIndex = targetTransform.GetSiblingIndex();

if (levels > levelRenderers.Count)
{
//initialize missing tree line level render
//initialize missing tree line level renderer
var startIndex = levelRenderers.Count;
int x;
for (x = startIndex; x < levels; x++)
Expand Down Expand Up @@ -413,34 +418,33 @@ public void Initialize(Transform transform)

public void OnGUI(Rect rect, GameObject target, int siblingIndex, bool isCurrentLevel)
{
//NOTE: currently we are using labels and predefined chars to display tree lines, this is not optimal solution
// since we can't really control width, tickiness and other potential useful properties. Using few chars allow us
// to display dashed lines very easily but replacing it with standard line would a bit harder.
// For now this is ok solution but probably should be replaced with drawing lines using the EditorGUI.DrawRect API,
// in the same way we draw lines in the Inspector
var offset = new Vector2()
{
x = EditorGUIUtility.standardVerticalSpacing
};

if (isCurrentLevel)
{
var hasChildren = target.transform.childCount > 0;
GUIContent label;
//NOTE: extend if there is no foldout button
var isLineExtended = target.transform.childCount == 0;
var horizontalSizeOffset = isLineExtended ? rect.width / 2 : 0.0f;
if (GetParentChildCount(target) == (siblingIndex + 1))
{
renderedLastLevelGameobject = true;
label = hasChildren ? Style.treeElementLastHalf : Style.treeElementLast;
HierarchyTreeUtility.DrawCornerLine(rect, isDashed, Style.treeLineTickness, Style.treeLineColor, offset, horizontalSizeOffset);
}
else
{
renderedLastLevelGameobject = false;
label = hasChildren ? Style.treeElementCrossHalf : Style.treeElementCross;
HierarchyTreeUtility.DrawCrossLine(rect, isDashed, Style.treeLineTickness, Style.treeLineColor, offset, horizontalSizeOffset);
}

EditorGUI.LabelField(rect, label, Style.treeElementStyle);
return;
}

if (!renderedLastLevelGameobject)
{
EditorGUI.LabelField(rect, Style.treeElementPass, Style.treeElementStyle);
HierarchyTreeUtility.DrawPassingLine(rect, isDashed, Style.treeLineTickness, Style.treeLineColor, offset);
}
}

Expand All @@ -462,34 +466,22 @@ private int GetParentChildCount(Transform transform)
}
}
}
#endregion
#endregion

protected static class Style
{
internal static readonly float minWidth = 17.0f;
internal static readonly float maxWidth = 60.0f;
internal static readonly float treeLineTickness = 0.75f;

internal static readonly GUIStyle defaultAlignTextStyle;
internal static readonly GUIStyle centreAlignTextStyle;
internal static readonly GUIStyle rightAlignTextStyle;
internal static readonly GUIStyle treeElementStyle;

internal static readonly GUIContent treeElementLast;
internal static readonly GUIContent treeElementLastHalf;
internal static readonly GUIContent treeElementCross;
internal static readonly GUIContent treeElementCrossHalf;
internal static readonly GUIContent treeElementPass;

internal static readonly Color characterColor;
internal static readonly Color treeLineColor = Color.white;

static Style()
{
treeElementLast = new GUIContent("└--");
treeElementLastHalf = new GUIContent("└-");
treeElementCross = new GUIContent("├--");
treeElementCrossHalf = new GUIContent("├-");
treeElementPass = new GUIContent("│");

defaultAlignTextStyle = new GUIStyle(EditorStyles.miniLabel)
{
#if UNITY_2019_3_OR_NEWER
Expand Down Expand Up @@ -518,16 +510,6 @@ static Style()
alignment = TextAnchor.UpperRight
#endif
};
treeElementStyle = new GUIStyle(EditorStyles.label)
{
padding = new RectOffset(4, 0, 0, 0),
fontSize = 12,
};

if (!EditorGUIUtility.isProSkin)
{
treeElementStyle.normal.textColor = Color.white;
}
}
}
}
Expand Down
103 changes: 103 additions & 0 deletions Assets/Editor Toolbox/Editor/Hierarchy/HierarchyTreeUtility.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
using UnityEditor;
using UnityEngine;

namespace Toolbox.Editor.Hierarchy
{
internal static class HierarchyTreeUtility
{
private const float dashLength = 4.0f;
private const float spaceLength = 1.0f;

private static Rect GetLineRect(Rect rect, float thickness, float padding, bool horizontal)
{
return horizontal
? new Rect(rect.x, rect.y + padding / 2, rect.width, thickness)
: new Rect(rect.x + padding / 2, rect.y, thickness, rect.height);
}

private static void DrawVerticalLine(Rect rect, bool isDashed, float tickness, Color color)
{
DrawVerticalLine(rect, isDashed, tickness, color, 0.0f);
}

private static void DrawVerticalLine(Rect rect, bool isDashed, float tickness, Color color, float paddingOffset)
{
rect = GetLineRect(rect, tickness, rect.width - paddingOffset, false);
if (!isDashed)
{
EditorGUI.DrawRect(rect, color);
return;
}

var dashesCount = rect.height / (dashLength + spaceLength);
var maxY = rect.yMax;

rect.yMax = rect.yMin + dashLength;
for (var i = 0; i < dashesCount; i++)
{
EditorGUI.DrawRect(rect, color);
rect.y += dashLength + spaceLength;
if (rect.yMax > maxY)
{
rect.yMax = maxY;
}
}
}

private static void DrawHorizontalLine(Rect rect, bool isDashed, float tickness, Color color)
{
DrawHorizontalLine(rect, isDashed, tickness, color, 0.0f);
}

private static void DrawHorizontalLine(Rect rect, bool isDashed, float tickness, Color color, float paddingOffset)
{
rect = GetLineRect(rect, tickness, rect.height - paddingOffset, true);
if (!isDashed)
{
EditorGUI.DrawRect(rect, color);
return;
}

var dashesCount = rect.width / (dashLength + spaceLength);
var maxX = rect.xMax;

rect.xMax = rect.xMin + dashLength;
for (var i = 0; i < dashesCount; i++)
{
EditorGUI.DrawRect(rect, color);
rect.x += dashLength + spaceLength;
if (rect.xMax > maxX)
{
rect.xMax = maxX;
}
}
}

public static void DrawPassingLine(Rect rect, bool isDashed, float tickness, Color color, Vector2 paddingOffset)
{
DrawVerticalLine(rect, isDashed, tickness, color, paddingOffset.x);
}

public static void DrawCornerLine(Rect rect, bool isDashed, float tickness, Color color, Vector2 paddingOffset, float horizontalSizeOffset)
{
//NOTE: -1 as a offset for halfs in corners
var verticalRect = rect;
verticalRect.yMax -= verticalRect.height / 2 - 1;
DrawVerticalLine(verticalRect, isDashed, tickness, color, paddingOffset.x);

var horizontalRect = rect;
horizontalRect.xMin += horizontalRect.width / 2;
horizontalRect.xMax += horizontalSizeOffset;
DrawHorizontalLine(horizontalRect, isDashed, tickness, color, paddingOffset.y);
}

public static void DrawCrossLine(Rect rect, bool isDashed, float tickness, Color color, Vector2 paddingOffset, float horizontalSizeOffset)
{
DrawVerticalLine(rect, isDashed, tickness, color, paddingOffset.x);

rect.xMin += rect.width / 2;
rect.xMax += horizontalSizeOffset;
DrawHorizontalLine(rect, isDashed, tickness, color, paddingOffset.y);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Assets/Editor Toolbox/EditorSettings.asset
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ MonoBehaviour:
useToolboxHierarchy: 1
drawHorizontalLines: 1
showSelectionsCount: 1
rowDataTypes: 050000000000000001000000020000000300000004000000
rowDataTypes: 05000000000000000100000004000000
useToolboxFolders: 1
largeIconScale: 0.8
smallIconScale: 0.7
Expand Down
1 change: 0 additions & 1 deletion Assets/Editor Toolbox/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -929,5 +929,4 @@ Assets/Create/Editor Toolbox/ScriptableObject Creation Wizard

Select a specific object that is under the cursor (default key: tab).

![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/sceneview.png)
![inspector](https://github.com/arimger/Unity-Editor-Toolbox/blob/develop/Docs/sceneview.png)

0 comments on commit 71168a5

Please sign in to comment.