using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Pool; using Object = UnityEngine.Object; namespace XericUI.ReflectionUIGenerator { /// /// 节点下生成反射属性管理器 — MVM (Metadata-Driven View Model) /// 负责:构建 Entry → 创建组容器(树状嵌套)→ 生成 UI → 绑定数据 /// public class XuiavrgInspectorManager : MonoBehaviour { #region 对象池 private Dictionary> _prefabPools = new Dictionary>(); public GameObject PrefabPoolGet(GameObject prefab) { if (prefab == null) return null; if (!_prefabPools.TryGetValue(prefab, out var pool)) { pool = new ObjectPool( createFunc: () => prefab != null ? Object.Instantiate(prefab, transform) : new GameObject("PropertyItem", typeof(RectTransform)), actionOnGet: go => go.SetActive(true), actionOnRelease: go => go.SetActive(false), actionOnDestroy: go => { if (go) Destroy(go); }, collectionCheck: false, defaultCapacity: 4, maxSize: 64 ); _prefabPools[prefab] = pool; } return pool.Get(); } public void PrefabPoolRelease(GameObject prefab, GameObject instance) { if (prefab == null || instance == null) return; if (_prefabPools.TryGetValue(prefab, out var pool)) { pool.Release(instance); } else { if (instance) Destroy(instance); } } public void ClearAllPrefabPools() { foreach (var pool in _prefabPools.Values) { pool.Clear(); } _prefabPools.Clear(); } #endregion #region 字段 public List CurrentEntries { get; private set; } = new List(); public AvrgMvvmBindingCollection CurrentBindingCollection { get; private set; } public AvrgMemberMetaDataSet CurrentMetaDataSet { get; private set; } /// /// 编组叶节点字典 — 完整 GroupPath → 对应层级的 XuiAvrgMDGroup /// private Dictionary _leafGroupMap = new Dictionary(); [Tooltip("类型-预制体映射配置 ScriptableObject")] public AvrgTypePrefabMappingConfig typePrefabMappingConfig; #endregion #region Unity 生命周期 private void OnEnable() { XuiavrgStyleDefaults.EnsureDefaults(); } private void OnDestroy() { ClearAll(); } #endregion #region 核心生命周期 public void BuildFromMetaDataSet(AvrgMemberMetaDataSet metaDataSet, AvrgMvvmBindingCollection bindingCollection = null) { ClearCurrentEntries(); CurrentMetaDataSet = metaDataSet; CurrentBindingCollection = bindingCollection; if (metaDataSet == null) { Debug.LogError("[Xuiavrg] 未指定元数据集,无法构建 Entry"); return; } foreach (var metaData in metaDataSet.MetaDataList) { if (metaData.Hide) continue; var entry = XuiFieldTempEntry.Get(); entry.Initialize( string.IsNullOrEmpty(metaData.GroupPath) ? metaData.MemberName : metaData.GroupPath, metaData.Tag, metaData.TagIndex); if (bindingCollection != null) { var scheduler = bindingCollection.Scheduler; var matchedBinding = bindingCollection.FindByMemberName(metaData.MemberName); if (matchedBinding != null) { entry.AddBinding(matchedBinding, scheduler); } else { foreach (var binding in bindingCollection) { entry.AddBinding(binding, scheduler); break; } } } entry.FieldOrder = metaData.FieldOrder; CurrentEntries.Add(entry); } OnPostBuildEntries(CurrentEntries); SortEntries(); } public void SetBindingCollection(AvrgMvvmBindingCollection bindingCollection) { CurrentBindingCollection = bindingCollection; if (CurrentEntries != null && bindingCollection != null) { var scheduler = bindingCollection.Scheduler; foreach (var entry in CurrentEntries) { if (entry is XuiFieldTempEntry tempEntry) { var matched = bindingCollection.FindByMemberName(entry.EntryName); if (matched != null) tempEntry.AddBinding(matched, scheduler); } } } } protected virtual void OnPostBuildEntries(List entries) { } private void SortEntries() { CurrentEntries.Sort((a, b) => { int orderCompare = a.FieldOrder.CompareTo(b.FieldOrder); if (orderCompare != 0) return orderCompare; return string.Compare(a.EntryName, b.EntryName, StringComparison.Ordinal); }); } // ============ 四阶段 GenerateUI ============ /// /// 生成 UI — 四阶段流程 /// Phase A: 按 GroupPath 分组 /// Phase B: 构建路径树,创建嵌套的 XuiAvrgMDGroup 容器 /// Phase C: 在叶节点容器内生成 UI 组件并绑定 /// Phase D: 处理非编组 Entry 直接放进根目录 /// public void GenerateUI() { if (CurrentEntries == null || CurrentEntries.Count == 0) { Debug.LogWarning("[Xuiavrg] 没有可生成的 Entry,请先调用 BuildFromMetaDataSet"); return; } // Phase A: 按完整 GroupPath 分组 var groupedEntries = new Dictionary>(); var ungroupedEntries = new List(); foreach (var entry in CurrentEntries) { string groupPath = GetGroupPathFromEntry(entry); if (!string.IsNullOrEmpty(groupPath)) { if (!groupedEntries.ContainsKey(groupPath)) groupedEntries[groupPath] = new List(); groupedEntries[groupPath].Add(entry); } else { ungroupedEntries.Add(entry); } } // Phase B: 构建树状嵌套组容器 _leafGroupMap.Clear(); BuildGroupTree(groupedEntries.Keys); // Phase C: 在叶节点容器内生成 UI foreach (var kvp in groupedEntries) { string groupPath = kvp.Key; var entries = kvp.Value; if (!_leafGroupMap.TryGetValue(groupPath, out var leafGroup)) continue; foreach (var entry in entries) { GenerateSingleUI(entry, leafGroup.contentRoot); } } // Phase D: 非编组 Entry 直接放进根 foreach (var entry in ungroupedEntries) { GenerateSingleUI(entry, transform); } } // ============ 树状编组容器构建 ============ private void BuildGroupTree(IEnumerable allGroupPaths) { var rootNode = new GroupTreeNode(null); foreach (var fullPath in allGroupPaths) { if (string.IsNullOrEmpty(fullPath)) continue; var segments = fullPath.Split('/'); var current = rootNode; for (int i = 0; i < segments.Length; i++) { string seg = segments[i]; if (!current.Children.ContainsKey(seg)) current.Children[seg] = new GroupTreeNode(seg); current = current.Children[seg]; } } CreateGroupGameObjects(rootNode, null, transform, ""); } private void CreateGroupGameObjects( GroupTreeNode node, XuiAvrgMDGroup parentGroup, Transform parentTransform, string accumulatedPath) { foreach (var kvp in node.Children) { string segName = kvp.Key; var childNode = kvp.Value; string childFullPath = string.IsNullOrEmpty(accumulatedPath) ? segName : accumulatedPath + "/" + segName; var groupGo = new GameObject($"Group [{childFullPath}]", typeof(RectTransform)); groupGo.transform.SetParent(parentTransform, false); var rect = groupGo.GetComponent(); rect.anchorMin = new Vector2(0, 1); rect.anchorMax = new Vector2(1, 1); rect.pivot = new Vector2(0.5f, 1); rect.sizeDelta = new Vector2(0, 0); var group = groupGo.AddComponent(); group.Initialize(childFullPath, 0, parentGroup); if (childNode.Children.Count == 0) { _leafGroupMap[childFullPath] = group; } CreateGroupGameObjects(childNode, group, group.contentRoot, childFullPath); } } private class GroupTreeNode { public string SegmentName { get; } public Dictionary Children { get; } public GroupTreeNode(string name) { SegmentName = name; Children = new Dictionary(); } } // ============ 生成单个 UI ============ private void GenerateSingleUI(IFieldEntry entry, Transform parent) { if (entry is not XuiFieldTempEntry tempEntry) return; var prefab = ResolvePrefab(entry); if (prefab == null) { Debug.LogWarning($"[Xuiavrg] 未找到 Entry '{entry.EntryName}' 的匹配预制体,跳过"); return; } entry.BoundPrefab = prefab; var uiInstance = PrefabPoolGet(prefab); if (uiInstance == null) return; uiInstance.name = entry.EntryName; uiInstance.transform.SetParent(parent, false); if (uiInstance.GetComponentInChildren(true) == null) { Debug.LogError( $"[Xuiavrg] 预制体 '{prefab.name}' 不符合生成要求:缺少 XUIAvrgMDValue 组件。请确保预制体根节点或其子节点包含 XUIAvrgMDValue 脚本。"); PrefabPoolRelease(prefab, uiInstance); return; } entry.BindUIComponent(uiInstance, null); entry.OnEntryBind(); } private string GetGroupPathFromEntry(IFieldEntry entry) { if (entry.Bindings != null && entry.Bindings.Count > 0) { var metaData = entry.Bindings[0].MetaData; if (metaData != null && !string.IsNullOrEmpty(metaData.GroupPath)) return metaData.GroupPath; } return null; } // ============ 预制体解析 (Tag + 类型匹配) ============ /// /// 预制体解析优先级: /// 1. Tag != None → 按 Tag + 类型匹配(无匹配时报错) /// 2. Tag == None → 按类型匹配 /// 3. defaultPrefab 回退 /// PrefabOverrideName 已移除,由 Tag + 类型匹配替代 /// private GameObject ResolvePrefab(IFieldEntry entry) { if (typePrefabMappingConfig == null) { Debug.LogError("[Xuiavrg] 未配置 typePrefabMappingConfig"); return null; } var bindings = entry.Bindings; var valueType = bindings?.Count > 0 ? bindings[0].MetaData?.ValueType : null; // 优先级 1: Tag != None → Tag + 类型匹配 if (entry.Tag != XuiavrgFieldTag.None && valueType != null) { var taggedPrefab = typePrefabMappingConfig.FindPrefabByTypeAndTag(valueType, entry.Tag); if (taggedPrefab != null) return taggedPrefab; Debug.LogError( $"[Xuiavrg] 指定 Tag '{entry.Tag}' 的预制体不存在 " + $"(Entry: '{entry.EntryName}', 类型: {valueType.Name}),跳过 UI 生成"); return null; } // 优先级 2: Tag == None → 按类型匹配 if (valueType != null) { var typeMatch = typePrefabMappingConfig.FindPrefabByType(valueType); if (typeMatch != null) return typeMatch; } // 优先级 3: defaultPrefab 回退 if (typePrefabMappingConfig.defaultPrefab != null) { Debug.LogWarning( $"[Xuiavrg] 类型 '{valueType?.Name ?? "未知"}' 无精确匹配,使用默认预制体 '{typePrefabMappingConfig.defaultPrefab.name}'"); return typePrefabMappingConfig.defaultPrefab; } Debug.LogError( $"[Xuiavrg] 类型 '{valueType?.Name ?? "未知"}' 无匹配预制体,且未配置 defaultPrefab"); return null; } // ============ 清理 ============ public void ClearAll() { ClearCurrentEntries(); ClearAllPrefabPools(); ClearGroups(); CurrentMetaDataSet = null; CurrentBindingCollection = null; } private void ClearCurrentEntries() { foreach (var entry in CurrentEntries) { if (entry.UIInstance != null && entry.BoundPrefab != null) { PrefabPoolRelease(entry.BoundPrefab, entry.UIInstance); } if (entry is XuiFieldTempEntry tempEntry) { XuiFieldTempEntry.Release(tempEntry); } } CurrentEntries.Clear(); } private void ClearGroups() { foreach (var kvp in _leafGroupMap) { if (kvp.Value != null && kvp.Value.gameObject != null) { Destroy(kvp.Value.gameObject); } } _leafGroupMap.Clear(); } #endregion } }