Data调整
This commit is contained in:
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Continentis.Mods;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
@@ -135,7 +136,244 @@ namespace SLSFramework.UModAssistance
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region List<string>选择器,通过类型查找资产,将其名称存储在列表中
|
||||
public partial class DataEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// (旧功能) 从 EditorContentCollection 中选择
|
||||
/// </summary>
|
||||
private void DrawContentSelector(SerializedProperty targetListProp, string groupName, string label = null)
|
||||
{
|
||||
if (!targetListProp.isExpanded) return;
|
||||
|
||||
DrawGenericSelectorButton($"Add {groupName}...", targetListProp, () =>
|
||||
{
|
||||
// 1. 查找所有配置文件
|
||||
var collections = FindAllModEditReferences();
|
||||
|
||||
if (collections == null || collections.Count == 0)
|
||||
{
|
||||
Debug.LogError("No 'EditorContentCollection' assets found in the project.");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. 整合所有文件中的同名 Group 数据
|
||||
List<string> aggregatedItems = new List<string>();
|
||||
bool groupFound = false;
|
||||
|
||||
foreach (var collection in collections)
|
||||
{
|
||||
var items = collection.GetItems(groupName);
|
||||
if (items != null && items.Count > 0)
|
||||
{
|
||||
aggregatedItems.AddRange(items);
|
||||
groupFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!groupFound)
|
||||
{
|
||||
Debug.LogWarning($"Group '{groupName}' not found in any EditorContentCollection.");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 3. 去重并返回 (使用 Linq 的 Distinct)
|
||||
return aggregatedItems.Distinct().ToList();
|
||||
}, $"Select {groupName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (新功能) 从当前对象的另一个字段 (List<string> 或 Dictionary) 中选择
|
||||
/// </summary>
|
||||
/// <param name="targetListProp">要添加元素的目标 List</param>
|
||||
/// <param name="sourceFieldName">数据源字段的变量名 (可以是 List<string> 或 Dictionary<string, T>)</param>
|
||||
/// <param name="label">可选标签</param>
|
||||
/// <param name="buttonLabel">可选按钮标签</param>
|
||||
private void DrawLocalContentSelector(SerializedProperty targetListProp, string sourceFieldName, string label = null, string buttonLabel = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(buttonLabel)) buttonLabel = $"Add from {sourceFieldName}...";
|
||||
|
||||
DrawGenericSelectorButton(buttonLabel, targetListProp, () =>
|
||||
{
|
||||
// 数据获取逻辑:利用反射从当前对象内部查找
|
||||
var targetObj = serializedObject.targetObject;
|
||||
// 支持私有和公有字段
|
||||
var field = targetObj.GetType().GetField(sourceFieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
|
||||
if (field != null)
|
||||
{
|
||||
var value = field.GetValue(targetObj);
|
||||
if (value != null)
|
||||
{
|
||||
// 情况 1: 它是 Dictionary (SerializableDictionary 或 普通 Dictionary)
|
||||
// 我们通过反射查找 "Keys" 属性,这样兼容性最好
|
||||
var keysProp = value.GetType().GetProperty("Keys");
|
||||
if (keysProp != null)
|
||||
{
|
||||
var keys = keysProp.GetValue(value) as System.Collections.IEnumerable;
|
||||
if (keys != null)
|
||||
{
|
||||
// 将所有 Key 转为 string 返回
|
||||
return keys.Cast<object>().Select(k => k.ToString()).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
// 情况 2: 它是 List<string> 或 string[]
|
||||
if (value is IEnumerable<string> list)
|
||||
{
|
||||
return list.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.LogWarning($"Could not find valid string list or dictionary keys in field '{sourceFieldName}'.");
|
||||
return null;
|
||||
}, $"Select from {sourceFieldName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 这是一个私有的通用辅助方法,处理按钮绘制和窗口调用
|
||||
/// </summary>
|
||||
private void DrawGenericSelectorButton(string buttonText, SerializedProperty targetListProp, Func<List<string>> dataProvider, string windowTitle)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
// 仅仅为了排版美观的占位
|
||||
// EditorGUILayout.LabelField("", GUILayout.Width(0));
|
||||
|
||||
if (GUILayout.Button(buttonText, GUILayout.Height(20)))
|
||||
{
|
||||
// 1. 获取数据 (执行传入的逻辑)
|
||||
List<string> items = dataProvider?.Invoke();
|
||||
|
||||
if (items != null && items.Count > 0)
|
||||
{
|
||||
// 2. 打开通用窗口
|
||||
ContentSelectorWindow.Show(windowTitle, items, (selectedItem) =>
|
||||
{
|
||||
// 3. 添加到列表的通用逻辑
|
||||
bool alreadyExists = false;
|
||||
for (int i = 0; i < targetListProp.arraySize; i++)
|
||||
{
|
||||
if (targetListProp.GetArrayElementAtIndex(i).stringValue == selectedItem)
|
||||
{
|
||||
alreadyExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!alreadyExists)
|
||||
{
|
||||
targetListProp.InsertArrayElementAtIndex(targetListProp.arraySize);
|
||||
targetListProp.GetArrayElementAtIndex(targetListProp.arraySize - 1).stringValue = selectedItem;
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Item '{selectedItem}' already exists.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 组合绘制:默认列表UI + 本地源选择按钮
|
||||
/// </summary>
|
||||
protected void DrawListWithLocalSelector(SerializedProperty listProp, string sourceFieldName, string label = null)
|
||||
{
|
||||
if (label != null) EditorGUILayout.PropertyField(listProp, new GUIContent(label), true);
|
||||
else EditorGUILayout.PropertyField(listProp, true);
|
||||
|
||||
if (listProp.isExpanded)
|
||||
{
|
||||
DrawLocalContentSelector(listProp, sourceFieldName);
|
||||
}
|
||||
//EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
// (DrawListWithContentSelector 保持不变,可以继续使用)
|
||||
protected void DrawListWithEditRefSelector(SerializedProperty listProp, string groupName, string label = null)
|
||||
{
|
||||
if (label != null) EditorGUILayout.PropertyField(listProp, new GUIContent(label), true);
|
||||
else EditorGUILayout.PropertyField(listProp, true);
|
||||
|
||||
if (listProp.isExpanded)
|
||||
{
|
||||
DrawContentSelector(listProp, groupName);
|
||||
}
|
||||
//EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
private static List<ModEditReference> FindAllModEditReferences()
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("t:ModEditReference");
|
||||
List<ModEditReference> results = new List<ModEditReference>();
|
||||
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
var asset = AssetDatabase.LoadAssetAtPath<ModEditReference>(AssetDatabase.GUIDToAssetPath(guid));
|
||||
if (asset != null)
|
||||
{
|
||||
results.Add(asset);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
// --- 重构后的通用窗口 ---
|
||||
private class ContentSelectorWindow : EditorWindow
|
||||
{
|
||||
private Action<string> _onSelectCallback;
|
||||
private List<string> _allItems; // 数据直接从外部传入
|
||||
private List<string> _filteredItems;
|
||||
private string _searchString = "";
|
||||
private Vector2 _scrollPos;
|
||||
|
||||
// Show 方法现在的签名变得更通用了,不再绑定 groupName
|
||||
public static void Show(string title, List<string> items, Action<string> onSelect)
|
||||
{
|
||||
var window = GetWindow<ContentSelectorWindow>(true, title, true);
|
||||
window.minSize = new Vector2(250, 300);
|
||||
window._onSelectCallback = onSelect;
|
||||
window._allItems = items; // 直接接收数据
|
||||
window.FilterList();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
GUILayout.BeginHorizontal(EditorStyles.toolbar);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
_searchString = GUILayout.TextField(_searchString, GUI.skin.FindStyle("ToolbarSearchTextField"));
|
||||
if (GUILayout.Button("", GUI.skin.FindStyle("ToolbarSearchCancelButton"))) _searchString = "";
|
||||
if (EditorGUI.EndChangeCheck()) FilterList();
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
_scrollPos = EditorGUILayout.BeginScrollView(_scrollPos);
|
||||
if (_filteredItems != null)
|
||||
{
|
||||
foreach (var item in _filteredItems)
|
||||
{
|
||||
if (GUILayout.Button(item, EditorStyles.label))
|
||||
{
|
||||
_onSelectCallback?.Invoke(item);
|
||||
// this.Close(); // 可选:点击后关闭
|
||||
}
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
private void FilterList()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_searchString)) _filteredItems = new List<string>(_allItems);
|
||||
else _filteredItems = _allItems.Where(i => i.IndexOf(_searchString, StringComparison.OrdinalIgnoreCase) >= 0).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Searchable Type选择器,将获取的类型名存入一个string中
|
||||
|
||||
public partial class DataEditor
|
||||
|
||||
Reference in New Issue
Block a user