Data调整

This commit is contained in:
SoulliesOfficial
2025-11-30 14:21:08 -05:00
parent ad4948207e
commit afbeeebe75
34 changed files with 533 additions and 202 deletions

View File

@@ -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