Unity文件夹注释工具

注:个人只在Unity2018及以上版本测试过,不保证其他版本是否能正常运行~

直接上测试效果图


在这里插入图片描述

使用方式

  1. 在Project窗口中选择任意文件夹
  2. 在Inspector窗口中编辑Comment
  3. 当关闭或者切换Inspector窗口时候会自动保存数据到文件中
    在这里插入图片描述

下面就是源码了,喜欢的朋友可以直接拿去用

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

//------------------------------------------------------------
// shaco Framework
// Copyright © 2017-2020 chang.liu All rights reserved.
// Feedback: 449612236@qq.com
//------------------------------------------------------------

namespace shaco.Instance.ProjectFolderAsset
{
    [CanEditMultipleObjects, CustomEditor(typeof(DefaultAsset))]
    public class ProjectFolderAssetInspector : UnityEditor.Editor
    {
        private List<string> _assetsPath = new List<string>();
        private string _comment = string.Empty;
        private bool _isCommentChanged = false;

        void OnEnable()
        {
            _assetsPath.Clear();
            for (int i = 0; i < targets.Length; ++i)
            {
                var assetPathTmp = AssetDatabase.GetAssetPath(targets[i]);
                if (!AssetDatabase.IsValidFolder(assetPathTmp))
                    continue;//@@@要支持多个设置

                _assetsPath.Add(assetPathTmp);
            }

            if (_assetsPath.Count > 0)
                _comment = ProjectFolderAssetDataManager.instance.AssetPathToComment(_assetsPath[0]);
        }

        void OnDestroy()
        {
            if (_isCommentChanged)
            {
                ProjectFolderAssetDataManager.instance.SaveToFile();
            }
        }

        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();

            //只处理文件夹显示
            if (0 == _assetsPath.Count)
                return;

            bool enabled = GUI.enabled;
            GUI.enabled = true;

            DrawFolder();

            GUI.enabled = enabled;
        }

        private void DrawFolder()
        {
            EditorGUILayout.PrefixLabel("Comment");

            GUI.changed = false;
            _comment = EditorGUILayout.TextArea(_comment, GUILayout.MinHeight(48));
            if (GUI.changed)
            {
                for (int i = 0; i < _assetsPath.Count; ++i)
                    ProjectFolderAssetDataManager.instance.SetComment(_assetsPath[i], _comment);

                _isCommentChanged = true;
                EditorUtility.SetDirty(target);

                EditorApplication.RepaintProjectWindow();
            }
        }
    }

    /// <summary>
    /// 编辑器文件夹绘制使用的相关数据管理器
    /// </summary>
    [InitializeOnLoad]
    public class ProjectFolderAssetDataManager
    {
        public class ProjectFolderAssetData
        {
            //该路径仅仅作为参考(方便查看配置文本),并无实际意义
            public string assetPath;
            public string comment;
        }

        static public ProjectFolderAssetDataManager instance
        {
            get
            {
                if (null == _instance)
                {
                    _instance = new ProjectFolderAssetDataManager();
                    _instance.LoadFromFile(_instance.SAVE_DATA_PATH);
                }
                return _instance;
            }
        }
        static private ProjectFolderAssetDataManager _instance = null;

        //保存路径
        private string SAVE_DATA_PATH
        {
            get
            {
                return Application.dataPath + "/../ProjectSettings/shacoProjectFolderAssetData.txt";
            }
        }

        //文件夹注释字典
        private Dictionary<string, ProjectFolderAssetData> _folderDatas = new Dictionary<string, ProjectFolderAssetData>();

        static ProjectFolderAssetDataManager()
        {
            EditorApplication.projectWindowItemOnGUI += ProjectWindowItemOnGUI;
        }

        /// <summary>
        /// 获取文件夹注释
        /// <param name="assetPath">文件夹路径</param>
        /// <return>文件夹注释,如果没有则返回空字符串</return>
        /// </summary>
        public string AssetPathToComment(string assetPath)
        {
            var guid = AssetDatabase.AssetPathToGUID(assetPath);
            return AssetGUIDToComment(guid);
        }

        /// <summary>
        /// 获取文件夹注释
        /// <param name="guid">文件夹唯一id</param>
        /// <return>文件夹注释,如果没有则返回空字符串</return>
        /// </summary>
        public string AssetGUIDToComment(string guid)
        {
            string retValue = null;
            ProjectFolderAssetData findData = null;
            if (_folderDatas.TryGetValue(guid, out findData))
                retValue = findData.comment;
            else
                retValue = string.Empty;

            return retValue;
        }

        /// <summary>
        /// 获取文件夹数据
        /// <param name="guid">文件夹唯一id</param>
        /// <return>文件夹数据,没有则返回空</return>
        /// </summary>
        public ProjectFolderAssetData GetFolderData(string guid)
        {
            ProjectFolderAssetData findData = null;
            _folderDatas.TryGetValue(guid, out findData);
            return findData;
        }

        /// <summary>
        /// 设置文件夹注释,并自动保存到文件
        /// <param name="assetPath">文件夹路径</param>
        /// <param name="comment">文件夹注释</param>
        /// </summary>
        public void SetComment(string assetPath, string comment)
        {
            if (string.IsNullOrEmpty(assetPath))
            {
                Debug.LogError("ProjectFolderAssetDataManager SetComment erorr: assetPath is empty");
                return;
            }

            if (!assetPath.StartsWith("Assets"))
            {
                Debug.LogError("ProjectFolderAssetDataManager SetComment erorr: not Unity project path=" + assetPath);
                return;
            }

            ProjectFolderAssetData findData = null;
            var guid = AssetDatabase.AssetPathToGUID(assetPath);
            if (!_folderDatas.TryGetValue(guid, out findData))
            {
                findData = new ProjectFolderAssetData();
                findData.assetPath = assetPath;
                findData.comment = comment;
                _folderDatas.Add(guid, findData);
            }
            else
            {
                if (string.IsNullOrEmpty(comment))
                    _folderDatas.Remove(guid);
                else
                {
                    findData.assetPath = assetPath;
                    findData.comment = comment;
                }
            }
        }

        /// <summary>
        /// 保存文件夹信息到文件中
        /// <param name="path">保存路径</param>
        /// </summary>
        public void SaveToFile()
        {
            SaveToFile(SAVE_DATA_PATH);
        }
        private void SaveToFile(string path)
        {
            if (_folderDatas.Count == 0)
            {
                System.IO.File.Delete(path);
                return;
            }

            var saveStr = new System.Text.StringBuilder();
            foreach (var iter in _folderDatas)
            {
                saveStr.Append(iter.Key);
                saveStr.Append('\n');
                saveStr.Append(iter.Value.assetPath);
                saveStr.Append('\n');
                saveStr.Append(iter.Value.comment);
                saveStr.Append('\n');
            }

            if (saveStr.Length > 0)
                saveStr.Remove(saveStr.Length - 1, 1);

            var directoryIath = new System.IO.DirectoryInfo(path).Parent;
            if (!directoryIath.Exists)
            {
                directoryIath.Create();
            }

            System.IO.File.WriteAllText(path, saveStr.ToString(), System.Text.Encoding.UTF8);
        }

        /// <summary>
        /// 从文件读取文件夹信息
        /// <param name="path">保存路径</param>
        /// </summary>
		private void LoadFromFile(string path)
        {
            _folderDatas.Clear();

            if (!System.IO.File.Exists(path))
                return;

            try
            {
                using (var readStream = new System.IO.StreamReader(path))
                {
                    while (true)
                    {
                        var guid = readStream.ReadLine();
                        if (string.IsNullOrEmpty(guid))
                            break;

                        var assetPath = readStream.ReadLine();
                        if (string.IsNullOrEmpty(assetPath))
                        {
                            throw new System.Exception("ProjectFolderAssetDataManager LoadFromFile error: not found assetPath, guid=" + guid);
                        }

                        var comment = readStream.ReadLine();
                        if (string.IsNullOrEmpty(comment))
                        {
                            throw new System.Exception("ProjectFolderAssetDataManager LoadFromFile error: not found comment, name=" + assetPath);
                        }

                        var folderAssestData = new ProjectFolderAssetData();
                        folderAssestData.assetPath = assetPath;
                        folderAssestData.comment = comment;

                        _folderDatas.Add(guid, folderAssestData);
                    }
                    readStream.Close();
                }
            }
            catch (System.Exception e)
            {
                Debug.LogError("ProjectFolderAssetDataManager LoadFromFile exception: e=" + e);
                System.IO.File.Delete(path);
            }
        }

        static private GUIStyle _guiStyleLabelTree = null;
        static private GUIStyle _guiStyleLabelNotTree = null;

        static private void ProjectWindowItemOnGUI(string guid, Rect selectionRect)
        {
            var folderData = ProjectFolderAssetDataManager.instance.GetFolderData(guid);
            if (null == folderData || string.IsNullOrEmpty(folderData.comment))
                return;

            if (null == _guiStyleLabelTree)
            {
                _guiStyleLabelTree = EditorStyles.label;
                _guiStyleLabelNotTree = EditorStyles.label;

                _guiStyleLabelTree.fontSize = 12;
                _guiStyleLabelNotTree.fontSize = 10;
            }

            var aliasContent = new GUIContent(folderData.comment);
            var isTree = IsTreeView(selectionRect);
            var labelStyle = isTree ? _guiStyleLabelTree : _guiStyleLabelNotTree;
            Vector2 labelSize = labelStyle.CalcSize(aliasContent);
            float offsetYWhenCurrentSelectAsset = 0;

            if (!isTree)
            {
                IsIconSmall(ref selectionRect);

                if (null != Selection.objects)
                {
                    if (null != System.Array.Find(Selection.objects, v => AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(v)) == guid))
                        offsetYWhenCurrentSelectAsset = -labelSize.y * 0.167f;
                }
            }

            Rect textRect = new Rect(
                selectionRect.x + Mathf.Max(0, (selectionRect.width - labelSize.x) * 0.5f),
                selectionRect.yMax + (isTree ? -labelSize.y - labelSize.y * 0.167f : labelSize.y * 0.33f - labelSize.y) + offsetYWhenCurrentSelectAsset,
                labelSize.x, labelSize.y);

            float cropWidth = selectionRect.width;

            if (isTree)
            {
                textRect.width = System.Math.Min(labelSize.x, selectionRect.width / 3);
                cropWidth = textRect.width;
                textRect.x = selectionRect.xMax - textRect.width;
                selectionRect.y = selectionRect.y;
            }

            aliasContent.text = CropText(labelStyle, aliasContent.text, cropWidth);
            EditorGUI.LabelField(textRect, aliasContent, labelStyle);
        }

        private static bool IsTreeView(Rect rect)
        {
            return rect.height <= 21f;
        }

        // https://github.com/PhannGor/unity3d-rainbow-folders/blob/master/Assets/Plugins/RainbowFolders/Editor/Scripts/RainbowFoldersBrowserIcons.cs
        private static bool IsIconSmall(ref Rect rect)
        {
            var isSmall = rect.width > rect.height;

            if (isSmall)
                rect.width = rect.height;
            else
                rect.height = rect.width;
            return isSmall;
        }

        static private System.Reflection.MethodInfo _getNumCharactersThatFitWithinWidth;

        /// <summary>
        /// UnityEditor.ObjectListArea - GetCroppedLabelText (G:1211)
        /// </summary>
        /// <param name="self"></param>
        /// <param name="text"></param>
        /// <param name="cropWidth"></param>
        /// <param name="symbol"></param>
        /// <returns></returns>
        public static string CropText(GUIStyle self, string text, in float cropWidth, string symbol = "…")
        {
            if (null == _getNumCharactersThatFitWithinWidth)
            {
                _getNumCharactersThatFitWithinWidth = typeof(GUIStyle).GetMethod("GetNumCharactersThatFitWithinWidth",
                    System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            }

            int thatFitWithinWidth = (int)_getNumCharactersThatFitWithinWidth.Invoke(self, new object[] { text, cropWidth });

            int num;
            switch (thatFitWithinWidth)
            {
                case -1:
                    return text;
                case 0:
                case 1:
                    num = 0;
                    break;
                default:
                    num = thatFitWithinWidth != text.Length ? 1 : 0;
                    break;
            }
            text = num == 0 ? text : text.Substring(0, thatFitWithinWidth - 1) + symbol;
            return text;
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值