using System;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace HK.PropertyAttribute
{
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(FilePathAttribute))]
public class FilePathDrawer : PropertyDrawer
{
private string[] _filePaths;
private string[] _displayNames;
private int _selectedIndex = -1;
private bool _isInitialized = false;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// 只处理字符串类型字段
if (property.propertyType != SerializedPropertyType.String)
{
EditorGUI.LabelField(position, label.text, "仅支持字符串类型字段");
return;
}
var attribute = (FilePathAttribute)base.attribute;
// 初始化文件列表
if (!_isInitialized)
{
InitializeFileList(attribute, property.stringValue);
_isInitialized = true;
}
// 绘制标签和下拉框
Rect labelRect = new Rect(position.x, position.y, EditorGUIUtility.labelWidth, position.height);
Rect fieldRect = new Rect(position.x + EditorGUIUtility.labelWidth, position.y,
position.width - EditorGUIUtility.labelWidth, position.height);
EditorGUI.LabelField(labelRect, label);
// 绘制下拉选择框
int newIndex = EditorGUI.Popup(fieldRect, _selectedIndex, _displayNames);
if (newIndex != _selectedIndex && newIndex >= 0 && newIndex < _filePaths.Length)
{
_selectedIndex = newIndex;
property.stringValue = _filePaths[newIndex];
property.serializedObject.ApplyModifiedProperties();
}
}
///
/// 初始化文件列表
///
private void InitializeFileList(FilePathAttribute attribute, string currentValue)
{
try
{
// 解析根路径(支持特殊路径)
string rootPath = ResolvePath(attribute.RootPath);
if (!Directory.Exists(rootPath))
{
_displayNames = new[] { $"路径不存在: {rootPath}" };
_filePaths = new[] { "" };
_selectedIndex = 0;
return;
}
// 获取所有文件
string[] allFiles = Directory.GetFiles(rootPath, "*.*", SearchOption.AllDirectories);
// 筛选文件扩展名
if (!string.IsNullOrEmpty(attribute.FileExtensions))
{
var extensions = attribute.FileExtensions
.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(ext => ext.Trim().ToLower()).ToList();
allFiles = allFiles.Where(file =>
extensions.Contains(Path.GetExtension(file).ToLower())).ToArray();
}
// 处理显示名称(相对路径)
_filePaths = allFiles;
_displayNames = allFiles.Select(file => GetRelativePath(rootPath, file)).ToArray();
// 找到当前值的索引
_selectedIndex = Array.IndexOf(_filePaths, currentValue);
// 如果当前值不在列表中,默认选中第一个
if (_selectedIndex == -1 && _filePaths.Length > 0)
{
_selectedIndex = 0;
}
}
catch (Exception ex)
{
_displayNames = new[] { $"错误: {ex.Message}" };
_filePaths = new[] { "" };
_selectedIndex = 0;
}
}
///
/// 解析特殊路径
///
private string ResolvePath(string path)
{
if (path.StartsWith("Application.dataPath"))
{
return path.Replace("Application.dataPath", Application.dataPath);
}
else if (path.StartsWith("Application.streamingAssetsPath"))
{
return path.Replace("Application.streamingAssetsPath", Application.streamingAssetsPath);
}
else if (path.StartsWith("Application.persistentDataPath"))
{
return path.Replace("Application.persistentDataPath", Application.persistentDataPath);
}
else if (path.StartsWith("Application.temporaryCachePath"))
{
return path.Replace("Application.temporaryCachePath", Application.temporaryCachePath);
}
// 相对路径转为绝对路径
if (!Path.IsPathRooted(path))
{
return Path.Combine(Application.dataPath, path);
}
return path;
}
///
/// 获取相对路径(用于显示)
///
private string GetRelativePath(string rootPath, string fullPath)
{
Uri rootUri = new Uri(rootPath + Path.DirectorySeparatorChar);
Uri fullUri = new Uri(fullPath);
return rootUri.MakeRelativeUri(fullUri).ToString().Replace('/', Path.DirectorySeparatorChar);
}
}
#endif
}