using System; using System.IO; using UnityEngine; using PlasticGui.WorkspaceWindow.Items; using Unity.PlasticSCM.Editor.UI; namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent { internal static class DrawExpandedTreeNode { internal const float ICON_SIZE = 66; internal const float PADDING = 5; internal static void Draw( Rect rect, ExpandedTreeNode node, bool isSelected, bool hasFocus, bool isDragTarget) { DrawIcon( new Rect( rect.x + (rect.width - ICON_SIZE) / 2, rect.y + PADDING, ICON_SIZE, ICON_SIZE), GetIcon(node), isSelected); string fileName = Path.GetFileName(node.GetFullPath()); DrawLabel( new Rect( rect.x + PADDING, rect.y + PADDING + ICON_SIZE, rect.width - 2 * PADDING, rect.height - ICON_SIZE - 2 * PADDING), ExpandedTreeNode.IsDirectory(node) ? fileName : GetFileNameWithoutExtension(fileName), fileName, isSelected, hasFocus, isDragTarget); } internal static Texture GetIcon(ExpandedTreeNode node) { if (ExpandedTreeNode.IsDirectory(node)) return Images.GetFolderIcon(); return Images.GetFileIcon(node.GetFullPath()); } static void DrawIcon(Rect rect, Texture icon, bool isSelected) { Color originalColor = GUI.color; try { if (isSelected) GUI.color *= UnityStyles.Colors.SelectedIcon; GUI.DrawTexture(rect, icon); } finally { GUI.color = originalColor; } } static void DrawLabel( Rect rect, string text, string tooltip, bool isSelected, bool hasFocus, bool isDragTarget) { GUIStyle normalStyle = UnityStyles.CloudDrive.ItemsListLabel; GUIStyle focusedStyle = UnityStyles.CloudDrive.ItemsListLabelFocused; float textWidth; string cutText = CutText( text, normalStyle, rect.width, out textWidth); Rect labelRect = new Rect( rect.x + (rect.width - textWidth) / 2, rect.y + (rect.height - normalStyle.lineHeight) / 2, textWidth, normalStyle.lineHeight); if (isSelected) { Rect selectionRect = new Rect( labelRect.x - 1, labelRect.y - 1, labelRect.width + 2, labelRect.height + 2); Color rectColor = hasFocus ? UnityStyles.Colors.SelectedFocusedTextBackground : UnityStyles.Colors.SelectedUnfocusedTextBackground; Texture2D selectionTexture = CreateRoundedRectTexture( selectionRect.size, radius: 1, borderColor: rectColor, fillColor: rectColor, thickness: 1); GUI.DrawTexture(selectionRect, selectionTexture); } if (isDragTarget) { Rect dragTargetRect = new Rect( rect.x, rect.y - 2, rect.width, rect.height + 4); Texture2D dragTexture = CreateRoundedRectTexture( dragTargetRect.size, radius: 6, borderColor: UnityStyles.Colors.SelectedFocusedDropLineBackground, fillColor: UnityStyles.Colors.SelectedFocusedDropLabelBackground, thickness: 2); GUI.DrawTexture(dragTargetRect, dragTexture); } GUI.Label( labelRect, new GUIContent(cutText, cutText == tooltip ? null : tooltip), isSelected && hasFocus ? focusedStyle : normalStyle); } static string CutText( string text, GUIStyle style, float availableWidth, out float usedWidth) { usedWidth = 0; availableWidth -= style.margin.horizontal + style.padding.horizontal; float fullTextWidth = style.CalcSize( new GUIContent(text)).x; if (fullTextWidth <= availableWidth) { usedWidth = fullTextWidth; return text; } string resultText = string.Empty; foreach (char c in text) { float currentWidth = style.CalcSize( new GUIContent(resultText + c + ELLIPSIS)).x; if (currentWidth > availableWidth) return resultText + ELLIPSIS; usedWidth = currentWidth; resultText += c; } return resultText + ELLIPSIS; } static string GetFileNameWithoutExtension(string fileName) { if (fileName.LastIndexOf(".") <= 0) return fileName; if (MetaPath.IsMetaPath(fileName)) fileName = MetaPath.GetPathFromMetaPath(fileName); if (fileName.LastIndexOf(".") <= 0) return fileName; return Path.GetFileNameWithoutExtension(fileName); } static Texture2D CreateRoundedRectTexture( Vector2 rectSize, float radius, Color borderColor, Color fillColor, float thickness) { int width = (int)rectSize.x; int height = (int)rectSize.y; radius = Math.Min(radius, Math.Min(width, height) / 2); thickness = Math.Min(radius, thickness); Texture2D result = new Texture2D(width, height, TextureFormat.ARGB32, false); Color32[] pixels = new Color32[width * height]; double outerRadiusSquared = Math.Pow(radius, 2); double innerRadiusSquared = Math.Pow(radius - thickness, 2); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int pixelIdx = y * width + x; double distanceSquared; if (InCorner(x, y, width, height, radius, out distanceSquared)) { if (distanceSquared > outerRadiusSquared) continue; pixels[pixelIdx] = distanceSquared >= innerRadiusSquared ? borderColor : fillColor; continue; } pixels[pixelIdx] = IsBorder(x, y, width, height, radius, thickness) ? borderColor : fillColor; } } result.SetPixels32(pixels); result.Apply(); return result; } static bool InCorner( int x, int y, float width, float height, float radius, out double distanceSquared) { bool inTop = y < radius; bool inBottom = y >= height - radius; bool inLeft = x < radius; bool inRight = x >= width - radius; if ((!inTop && !inBottom) || (!inLeft && !inRight)) { distanceSquared = 0; return false; } float centerX = inLeft ? radius : width - radius - 1; float centerY = inTop ? radius : height - radius - 1; float deltaX = x - centerX; float deltaY = y - centerY; distanceSquared = Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2); return true; } static bool IsBorder(int x, int y, float width, float height, float radius, float thickness) { if (y < thickness && x >= radius && x < width - radius) // top border return true; if (y >= height - thickness && x >= radius && x < width - radius) // bottom border return true; if (x < thickness && y >= radius && y < height - radius) // left border return true; if (x >= width - thickness && y >= radius && y < height - radius) // right border return true; return false; } const string ELLIPSIS = "..."; } }