146 lines
5.3 KiB
C#
146 lines
5.3 KiB
C#
|
using System;
|
|||
|
using System.IO;
|
|||
|
using System.Linq;
|
|||
|
using UnityEditor;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
namespace HK.PropertyAttribute
|
|||
|
{
|
|||
|
[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();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 初始化文件列表
|
|||
|
/// </summary>
|
|||
|
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;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 解析特殊路径
|
|||
|
/// </summary>
|
|||
|
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;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 获取相对路径(用于显示)
|
|||
|
/// </summary>
|
|||
|
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);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|