347 lines
12 KiB
C#
347 lines
12 KiB
C#
#if UNITY_EDITOR && UNITY_2021_3_OR_NEWER
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using System.Text;
|
||
using System.Text.RegularExpressions;
|
||
using UnityEditor;
|
||
using UnityEngine;
|
||
using UnityEngine.Windows;
|
||
|
||
[InitializeOnLoad]
|
||
public class ZFolderIcons : EditorWindow
|
||
{
|
||
private static GUIStyle DirectoryLabelStyle;
|
||
private static GUIStyle MonoScriptLabelStyle;
|
||
private const float maxHeight = 18f;
|
||
|
||
private static Texture2D scriptIconTexture;
|
||
|
||
private static Dictionary<Regex, string> PreDefinedFolderLabels = new Dictionary<Regex, string>
|
||
{
|
||
{
|
||
new Regex(@"^Script(s)?$", RegexOptions.IgnoreCase),
|
||
"C#"
|
||
},
|
||
{
|
||
new Regex(@"^Plugin(s)?$", RegexOptions.IgnoreCase),
|
||
"Plug"
|
||
},
|
||
{
|
||
new Regex(@"^Resource(s)?$", RegexOptions.IgnoreCase),
|
||
"Res"
|
||
},
|
||
{
|
||
new Regex(@"^Editor$", RegexOptions.IgnoreCase),
|
||
"Edit"
|
||
},
|
||
{
|
||
new Regex(@"^Prefab(s)?$", RegexOptions.IgnoreCase),
|
||
"PF"
|
||
},
|
||
{
|
||
new Regex(@"^Tile(s)?Palette(s)?$", RegexOptions.IgnoreCase),
|
||
"Tile"
|
||
},
|
||
};
|
||
|
||
static ZFolderIcons()
|
||
{
|
||
EditorApplication.projectWindowItemOnGUI += OnProjectWindowItemGUI;
|
||
}
|
||
|
||
private static void OnProjectWindowItemGUI(string guid, Rect selectionRect)
|
||
{
|
||
if (selectionRect.height < maxHeight)
|
||
return;
|
||
|
||
// Get the asset path based on the GUID
|
||
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
||
|
||
// Check if the asset is a folder and not in the base project folder
|
||
// Use "&& assetPath.Count(c => c == '/') >= 2" to ignore base assets folder
|
||
|
||
// TODO: Impliment AssetDatabase.GetMainAssetTypeFromGUID(new GUID(guid)).IsSubclassOf(typeof(ScriptableObject))
|
||
|
||
Type objectType = null;
|
||
if (AssetDatabase.IsValidFolder(assetPath))
|
||
{
|
||
DoFolderIcons(assetPath, selectionRect);
|
||
}
|
||
else
|
||
{
|
||
objectType = AssetDatabase.GetMainAssetTypeFromGUID(new GUID(guid));
|
||
}
|
||
|
||
if (objectType == null) return;
|
||
if (objectType == typeof(MonoScript)) // Is script object
|
||
{
|
||
DoMonoScriptIcon(assetPath, selectionRect);
|
||
}
|
||
}
|
||
|
||
static void DoFolderIcons(string folderPath, Rect selectionRect)
|
||
{
|
||
// Calculate the position for the custom label
|
||
Rect labelRect = new Rect(selectionRect.x + selectionRect.width * 0.15f, selectionRect.y + selectionRect.width * 0.4f, selectionRect.width, selectionRect.height);
|
||
|
||
string folderName = Path.GetFileName(folderPath);
|
||
|
||
// Create GUIStyle if it hasn't been created yet
|
||
if (DirectoryLabelStyle == null)
|
||
{
|
||
DirectoryLabelStyle = new GUIStyle(EditorStyles.miniLabel);
|
||
DirectoryLabelStyle.alignment = TextAnchor.UpperLeft; // Adjust the font size as desired
|
||
DirectoryLabelStyle.normal.textColor = Color.black; // Set the text color
|
||
|
||
TryAssignFont(ref DirectoryLabelStyle);
|
||
}
|
||
DirectoryLabelStyle.fontSize = (int)(selectionRect.width * 0.35f); // Adjust the font size as desired
|
||
|
||
string labelText;
|
||
if (TryGetPreDefinedLabel(folderName, out string label))
|
||
{
|
||
labelText = label;
|
||
}
|
||
else if (folderName.Count(char.IsUpper) >= 2)
|
||
{
|
||
labelText = new string(folderName.Where(x => char.IsUpper(x)).Take(4).ToArray());
|
||
}
|
||
else
|
||
{
|
||
labelText = new(folderName.Take(4).ToArray());
|
||
}
|
||
|
||
// Draw the custom label with black color
|
||
var previousColor = GUI.color;
|
||
GUI.color = Color.black;
|
||
EditorGUI.LabelField(labelRect, labelText, DirectoryLabelStyle);
|
||
GUI.color = previousColor;
|
||
|
||
DrawFolderColorStrip(folderName, selectionRect);
|
||
}
|
||
|
||
static void DrawFolderColorStrip(string seedString, Rect selectionRect)
|
||
{
|
||
Color stripColor = GetRandomColor(seedString);
|
||
|
||
// Calculate the position for the strip
|
||
Rect stripRect = new Rect(
|
||
x: selectionRect.x + selectionRect.width * 0.175f,
|
||
y: selectionRect.y + selectionRect.width * 0.725f,
|
||
width: selectionRect.width * 0.64f,
|
||
height: selectionRect.height * 0.05f);
|
||
|
||
// Draw the custom label with black color
|
||
var previousColor = GUI.color;
|
||
EditorGUI.DrawRect(stripRect, stripColor);
|
||
GUI.color = previousColor;
|
||
}
|
||
|
||
static void DoMonoScriptIcon(string scriptPath, Rect selectionRect)
|
||
{
|
||
// Calculate the position for the white overlay
|
||
Rect overwriteOverlayRect = new Rect(selectionRect.x + selectionRect.width * 0.25f, selectionRect.y + selectionRect.width * 0.20f, selectionRect.width*0.5f, selectionRect.height*0.5f);
|
||
var previousColor = GUI.color;
|
||
|
||
if (!Application.isPlaying)
|
||
{
|
||
// Draw the custom rect with white color
|
||
previousColor = GUI.color;
|
||
float shadeOfWhite = 247;
|
||
GUI.color = new Color(shadeOfWhite / 255f, shadeOfWhite / 255f, shadeOfWhite / 255f);
|
||
EditorGUI.DrawRect(overwriteOverlayRect, GUI.color);
|
||
GUI.color = previousColor;
|
||
}
|
||
else
|
||
{
|
||
//Did not work
|
||
|
||
|
||
//// Gets playmode tint color
|
||
//string prefPlaymodeTint = EditorPrefs.GetString("Playmode tint", "").Replace("Playmode tint;", "");
|
||
//string[] rgba = prefPlaymodeTint.Split(";");
|
||
//Color color = new Color(float.Parse(rgba[0]), float.Parse(rgba[1]), float.Parse(rgba[2]), float.Parse(rgba[3]));
|
||
|
||
//// Draw the custom rect with play color tint
|
||
//previousColor = GUI.color;
|
||
//GUI.color = color;
|
||
//EditorGUI.DrawRect(overwriteOverlayRect, GUI.color);
|
||
//GUI.color = previousColor;
|
||
|
||
// Draw the custom rect with white color
|
||
previousColor = GUI.color;
|
||
float shadeOfWhite = 247;
|
||
GUI.color = new Color(shadeOfWhite / 255f, shadeOfWhite / 255f, shadeOfWhite / 255f);
|
||
EditorGUI.DrawRect(overwriteOverlayRect, GUI.color);
|
||
GUI.color = previousColor;
|
||
}
|
||
|
||
|
||
string scriptName = Path.GetFileName(scriptPath);
|
||
|
||
const int maxLength = 8;
|
||
string labelText;
|
||
{
|
||
// Use LINQ to iterate through each character and insert a line break before uppercase letters
|
||
labelText = new string(scriptName.SelectMany(c => char.IsUpper(c) ? new char[] { '\n', c } : new[] { c }).ToArray());
|
||
labelText = labelText.TrimStart('\n').Replace(".cs", "");
|
||
labelText = string.Join('\n', MergeLooseCapitalStrings(labelText.Split('\n')));
|
||
labelText = string.Join('\n', labelText.Split('\n').Select(x => x.Length > 6 ? new string(x.Take(maxLength).ToArray()) + "<22>" : x));
|
||
}
|
||
|
||
// Calculate the position for the custom label
|
||
Rect labelRect = new Rect(selectionRect.x + selectionRect.width * 0.15f, selectionRect.y + selectionRect.width * 0.1f, selectionRect.width, selectionRect.height);
|
||
|
||
// Create GUIStyle if it hasn't been created yet
|
||
if (MonoScriptLabelStyle == null)
|
||
{
|
||
MonoScriptLabelStyle = new GUIStyle(EditorStyles.miniLabel);
|
||
MonoScriptLabelStyle.alignment = TextAnchor.UpperLeft; // Adjust the font size as desired
|
||
MonoScriptLabelStyle.normal.textColor = Color.black; // Set the text color
|
||
|
||
TryAssignFont(ref MonoScriptLabelStyle);
|
||
}
|
||
MonoScriptLabelStyle.fontSize = (int)(selectionRect.width * 0.2f); // Adjust the font size as desired
|
||
|
||
// Draw the custom label with black color
|
||
previousColor = GUI.color;
|
||
GUI.color = Color.black;
|
||
EditorGUI.LabelField(labelRect, labelText, MonoScriptLabelStyle);
|
||
GUI.color = previousColor;
|
||
|
||
// Custom icon rect
|
||
Rect customIconRect = new Rect(selectionRect.x + selectionRect.width * 0.62f, selectionRect.y + selectionRect.width * 0.645f, selectionRect.width * 0.25f, selectionRect.height * 0.25f);
|
||
|
||
// Load texture if null
|
||
if (scriptIconTexture == null)
|
||
{
|
||
if (TryGetScriptIcon(out Texture2D icon))
|
||
{
|
||
scriptIconTexture = icon;
|
||
}
|
||
else
|
||
{
|
||
return; // Couldn't get icon, so don't draw it
|
||
}
|
||
}
|
||
|
||
// Draw the custom icon
|
||
GUI.DrawTexture(customIconRect, scriptIconTexture);
|
||
}
|
||
|
||
public static bool TryGetPreDefinedLabel(string folderName, out string label)
|
||
{
|
||
foreach (var regex in PreDefinedFolderLabels.Keys)
|
||
{
|
||
if (regex.IsMatch(folderName))
|
||
{
|
||
label = PreDefinedFolderLabels[regex];
|
||
return true;
|
||
}
|
||
}
|
||
|
||
label = "Error";
|
||
return false;
|
||
}
|
||
|
||
static bool TryGetScriptIcon(out Texture2D icon)
|
||
{
|
||
if (FindFolder("ExtraIcons", out string path))
|
||
{
|
||
icon = AssetDatabase.LoadAssetAtPath<Texture2D>(path + "/ScriptHashtag.png");
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
icon = null;
|
||
return false;
|
||
}
|
||
}
|
||
|
||
static bool FindFolder(string folderName, out string path)
|
||
{
|
||
string[] guids = AssetDatabase.FindAssets("t:Folder " + folderName);
|
||
|
||
if (guids.Length > 0)
|
||
{
|
||
path = AssetDatabase.GUIDToAssetPath(guids[0]);
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
path = null;
|
||
return false;
|
||
}
|
||
}
|
||
|
||
static string[] MergeLooseCapitalStrings(string[] arr)
|
||
{
|
||
List<string> result = new List<string>();
|
||
string currentString = "";
|
||
|
||
foreach (string s in arr)
|
||
{
|
||
if (IsUpperCase(s))
|
||
{
|
||
currentString += s;
|
||
}
|
||
else if (!string.IsNullOrEmpty(currentString))
|
||
{
|
||
result.Add(currentString + s);
|
||
currentString = "";
|
||
}
|
||
else
|
||
{
|
||
result.Add(s);
|
||
}
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(currentString))
|
||
{
|
||
result.Add(currentString);
|
||
}
|
||
|
||
return result.ToArray();
|
||
}
|
||
|
||
static Func<string, bool> IsUpperCase = s => !string.IsNullOrEmpty(s) && s.All(char.IsUpper);
|
||
|
||
/// <summary>
|
||
/// Generates a semi random color out of a seed
|
||
/// </summary>
|
||
/// <param name="seed">Used to generate the color</param>
|
||
/// <returns>A semi random color</returns>
|
||
public static Color GetRandomColor(string seed)
|
||
{
|
||
int intSeed = seed.Select(c=>(int)c).Sum();
|
||
|
||
System.Random random = new System.Random(intSeed);
|
||
|
||
// Generate random values for R, G, and B components between 0 and 1.
|
||
float r = (float)random.NextDouble();
|
||
float g = (float)random.NextDouble();
|
||
float b = (float)random.NextDouble();
|
||
|
||
// Create and return the color.
|
||
return new Color(r, g, b);
|
||
}
|
||
|
||
private static void TryAssignFont(ref GUIStyle guiFont)
|
||
{
|
||
string[] guids = AssetDatabase.FindAssets("t:Font CozetteVector", new[] { "Assets/Plugins/ZFolderIcons" });
|
||
|
||
|
||
if (guids.Length <= 0)
|
||
{
|
||
return; // Couldn't find font asset
|
||
}
|
||
|
||
string path = AssetDatabase.GUIDToAssetPath(guids[0]);
|
||
guiFont.font = AssetDatabase.LoadAssetAtPath<Font>(path);
|
||
}
|
||
}
|
||
#endif
|