BITKit/Src/UnityEditor/ScriptableObjectGroupEditor.cs

280 lines
7.9 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BITKit.UX;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using Object = UnityEngine.Object;
namespace BITKit.GameEditor
{
public class ScriptableObjectGroupEditor<T> : EditorWindow where T : ScriptableObject
{
protected virtual string AssetsPath => $"Assets/Artists/";
protected virtual string ExportPathKey => $"{typeof(T).Name}.ExportPath";
protected virtual string ExportNameKey=> $"{typeof(T).Name}.ExportName";
protected readonly List<T> List=new();
protected ListView listView { get; private set; }
protected VisualElement container { get; private set; }
protected VisualElement _actionContainer { get; private set; }
protected TextField _newNameField { get; private set; }
protected VisualElement ToolBarContainer { get; private set; }
private Button _createButton;
protected virtual void OnEnable()
{
RebuildList();
rootVisualElement.style.flexDirection = FlexDirection.Row;
var css = AssetDatabase.LoadAssetAtPath<StyleSheet>(BITEditorUtils.InspectorPath);
rootVisualElement.styleSheets.Add(css);
var leftSlider = rootVisualElement.Create<VisualElement>();
leftSlider.name = "LeftSlider";
ToolBarContainer = leftSlider.Create<VisualElement>();
ToolBarContainer.style.alignSelf = Align.Auto;
ToolBarContainer.style.flexDirection = FlexDirection.Row;
var refreshButton = ToolBarContainer.Create<Button>();
refreshButton.text = "刷新";
refreshButton.clicked += () =>
{
RebuildList();
listView.Rebuild();
};
var container = leftSlider.Create<VisualElement>();
var listViewContainer = container.Create<VisualElement>();
var createContainer = listViewContainer.Create<VisualElement>();
var exportButton = leftSlider.Create<Button>();
exportButton.text = "导出";
exportButton.clicked += ExportData;
_actionContainer = leftSlider.Create<VisualElement>();
createContainer.style.flexDirection = FlexDirection.Row;
var nameField = createContainer.Create<TextField>();
nameField.style.flexGrow = 1;
_createButton=createContainer.Create<Button>();
_createButton.text = "创建";
_createButton.clicked += () => CreateScriptableObject(nameField.value);
container.style.flexDirection = FlexDirection.Row;
listViewContainer.style.flexDirection = FlexDirection.Column;
listViewContainer.style.flexGrow = 1;
listViewContainer.Create<Label>().text = $"获取到:{List.Count}个配置";
listViewContainer.AddToClassList("pa-8");
listView = leftSlider.Create<ListView>();
listView.makeItem = MakeItem;
listView.bindItem = BindItem;
listView.itemsChosen += ItemsChosen;
listView.style.minWidth = 128;
listView.style.flexGrow = 1;
listView.itemsSource = List;
var scroll = rootVisualElement.Create<ScrollView>();
scroll.name = "Scroll";
scroll.style.flexGrow = 1;
{
var newNameContainer = scroll.Create<GroupBox>();
newNameContainer.style.flexDirection = FlexDirection.Row;
var newNameField =_newNameField = newNameContainer.Create<TextField>();
newNameField.style.flexGrow = 1;
var confirmButton = newNameContainer.Create<Button>();
confirmButton.text = "重命名";
confirmButton.clicked += () =>
{
var newName = newNameField.value;
if (string.IsNullOrEmpty(newName))
{
EditorUtility.DisplayDialog("警告", "文件名不能为空", "OK");
return;
}
var selected = listView.selectedItem as Object;
if(!selected)return;
var path = AssetDatabase.GetAssetPath(selected);
if (EditorUtility.DisplayDialog("询问", $"确定要重命名{Path.GetFileName(path)}为{newName}", "确定", "取消") is false)
{
return;
}
AssetDatabase.RenameAsset(path, newName);
RebuildList();
};
}
this.container = scroll.Create<GroupBox>();
var pingButton = ToolBarContainer.Create<Button>();
pingButton.text = "Ping";
pingButton.clicked += () =>
{
if (listView.selectedIndex < 0) return;
var item = List[listView.selectedIndex];
EditorGUIUtility.PingObject(item);
};
//_container.style.flexGrow = 1;
Debug.Log(
$"{GetType().Name} 已初始化,从{AssetsPath}获取到{List.Count}个{typeof(T).Name}");
}
private void ExportData()
{
var path = Environment.CurrentDirectory;
if (PlayerPrefs.HasKey(ExportPathKey))
{
path = PlayerPrefs.GetString(ExportPathKey);
}
var exportPath = EditorUtility.SaveFilePanel("select path", path, $"{typeof(T).Name}.bytes", "bytes");
if(string.IsNullOrEmpty(exportPath))return;
PlayerPrefs.SetString(ExportPathKey, exportPath);
PlayerPrefs.Save();
ExportData(exportPath);
BIT4Log.Log<ScriptableObjectGroupEditor<T>>($"导出成功:{exportPath}");
}
protected virtual void ExportData(string path)
{
throw new NotImplementedException($"暂未实现{typeof(T).Name}的导出功能");
}
protected virtual void ItemsChosen(IEnumerable<object> obj)
{
var selected = obj.FirstOrDefault() as Object;
var serializedObject = new SerializedObject(selected);
BITInspectorExtensions.FillDefaultInspector(container, serializedObject, true);
container.Bind(serializedObject);
if (selected)
_newNameField.SetValueWithoutNotify(selected.name);
}
protected virtual VisualElement MakeItem()
{
var container = new VisualElement();
var icon = container.Create<VisualElement>();
var label = container.Create<Label>();
icon.name = nameof(VisualElement) + "--0";
label.name = nameof(Label) + "--0";
container.style.flexDirection = FlexDirection.Row;
container.style.alignContent = Align.Center;
container.style.alignItems = Align.Center;
icon.style.width = 24;
icon.style.height = 24;
container.AddManipulator(new ContextualMenuManipulator((evt) =>
{
evt.menu.AppendAction("复制", Copy, DropdownMenuAction.AlwaysEnabled);
//evt.menu.AppendAction("Second menu item", (x) => Debug.Log("Second!!!!"), DropdownMenuAction.AlwaysEnabled);
}));
return container;
void Copy(DropdownMenuAction dropdownMenuAction)
{
if (container.userData is not ScriptableObject scriptableObject) return;
var path = AssetDatabase.GetAssetPath(scriptableObject);
var folder = Path.GetDirectoryName(path)!;
path = Path.Combine(folder, $"{scriptableObject.name}Copy.asset");
var newObject = CreateInstance<T>();
AssetDatabase.CreateAsset(newObject, path);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
RebuildList();
Debug.Log($"复制成功:{path}");
}
}
protected virtual void BindItem(VisualElement arg1, int arg2)
{
try
{
var item = List[arg2];
arg1.Q<Label>().text = item.name;
arg1.userData = item;
}
catch (Exception e)
{
Debug.LogException(e);
}
}
protected virtual void RebuildList()
{
container?.Clear();
List.Clear();
var paths = AssetDatabase.FindAssets($"t:{typeof(T).Name}");
var allItem =
(
from path in paths.Select(AssetDatabase.GUIDToAssetPath)
select AssetDatabase.LoadAssetAtPath<ScriptableObject>(path)
).ToArray();
List.AddRange(allItem.Cast<T>());
}
protected virtual void CreateScriptableObject(string name)
{
if (string.IsNullOrEmpty(name))
{
name = $"New {typeof(T).Name}";
}
var path = $"{AssetsPath}{name}.asset";
if (EditorUtility.DisplayDialog("创建", $"是否创建{name}到{path}?", "是", "否") is false) return;
new DirectoryInfo(Path.GetDirectoryName(path)!).Create();
var item = CreateInstance<T>();
item.name = name;
AssetDatabase.CreateAsset(item, path);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
List.Add(item);
listView.Rebuild();
ItemsChosen(new[] {item});
}
}
}