From 648269d5095aadc45048c56d0d974cf7c0eeb1ac Mon Sep 17 00:00:00 2001 From: TRADER_FOER Date: Sat, 2 May 2026 22:10:19 +0800 Subject: [PATCH] Signed-off-by: TRADER_FOER --- Assets/FR2_Cache.asset | 116 ++++++++-------- .../Elements/Composite/AddNewButton.prefab | 9 +- Assets/Scenes/EditorScene.unity | 5 +- .../Scripts/DynamicUI/Hierarchy/Hierarchy.cs | 100 ++++++-------- .../DynamicUI/Hierarchy/HierarchyTab.cs | 124 +++++++++++++++--- .../DynamicUI/MainUI/ToolBar/ToolBar.cs | 2 +- Assets/Scripts/Manager/EditorManager.cs | 16 +-- Assets/Scripts/Manager/OperationManager.cs | 1 + Assets/Scripts/Manager/ProjectContainer.cs | 2 - .../AutoSave/新世纪wow战士/AutoSave_0.json | 6 +- .../AutoSave/新世纪wow战士/AutoSave_1.json | 4 +- .../AutoSave/新世纪wow战士/AutoSave_2.json | 16 +-- 12 files changed, 236 insertions(+), 165 deletions(-) diff --git a/Assets/FR2_Cache.asset b/Assets/FR2_Cache.asset index 8786ca2f..5f73056c 100644 --- a/Assets/FR2_Cache.asset +++ b/Assets/FR2_Cache.asset @@ -20738,15 +20738,15 @@ MonoBehaviour: UseGUIDsList: [] - guid: 914dd73ddae7943148ea71537167542b type: 2 - m_fileInfoHash: 15663.cs + m_fileInfoHash: 15573.cs m_assetbundle: m_addressable: m_atlas: - m_fileSize: 15663 - m_assetChangeTS: 1777726759 - m_fileInfoReadTS: 1777726781 - m_fileWriteTS: 1777726743 - m_cachefileWriteTS: 1777726743 + m_fileSize: 15573 + m_assetChangeTS: 1777727161 + m_fileInfoReadTS: 1777727181 + m_fileWriteTS: 1777727159 + m_cachefileWriteTS: 1777727159 refreshStamp: 2 UseGUIDsList: [] - guid: 919d97c1a707113409177d498d31cf51 @@ -50894,15 +50894,15 @@ MonoBehaviour: UseGUIDsList: [] - guid: 54748045ed19d4ea6889de9b617f6f8b type: 2 - m_fileInfoHash: 9014.cs + m_fileInfoHash: 8287.cs m_assetbundle: m_addressable: m_atlas: - m_fileSize: 9014 - m_assetChangeTS: 1768707670 - m_fileInfoReadTS: 1768707686 - m_fileWriteTS: 1768707659 - m_cachefileWriteTS: 1768707659 + m_fileSize: 8287 + m_assetChangeTS: 1777730561 + m_fileInfoReadTS: 1777730581 + m_fileWriteTS: 1777730541 + m_cachefileWriteTS: 1777730541 refreshStamp: 2 UseGUIDsList: [] - guid: 5474cb78511de04459cac50d50b9d9e0 @@ -71132,15 +71132,15 @@ MonoBehaviour: UseGUIDsList: [] - guid: 16fbe890712a645c9ba3004c732c9d18 type: 2 - m_fileInfoHash: 14348.cs + m_fileInfoHash: 17062.cs m_assetbundle: m_addressable: m_atlas: - m_fileSize: 14348 - m_assetChangeTS: 1770973719 - m_fileInfoReadTS: 1770973737 - m_fileWriteTS: 1770973715 - m_cachefileWriteTS: 1770973715 + m_fileSize: 17062 + m_assetChangeTS: 1777730632 + m_fileInfoReadTS: 1777730650 + m_fileWriteTS: 1777730579 + m_cachefileWriteTS: 1777730579 refreshStamp: 2 UseGUIDsList: [] - guid: 164c9b1458eaab743a4b45c37a4d720d @@ -87161,15 +87161,15 @@ MonoBehaviour: UseGUIDsList: [] - guid: 773c77098921d4c1a87dc6068b5253e8 type: 2 - m_fileInfoHash: 6001.cs + m_fileInfoHash: 6087.cs m_assetbundle: m_addressable: m_atlas: - m_fileSize: 6001 - m_assetChangeTS: 1759647369 - m_fileInfoReadTS: 1759647388 - m_fileWriteTS: 1759647363 - m_cachefileWriteTS: 1759647363 + m_fileSize: 6087 + m_assetChangeTS: 1777730330 + m_fileInfoReadTS: 1777730351 + m_fileWriteTS: 1777730307 + m_cachefileWriteTS: 1777730307 refreshStamp: 2 UseGUIDsList: [] - guid: 774c00e683b6094459a1ed557b35694b @@ -128835,15 +128835,15 @@ MonoBehaviour: UseGUIDsList: [] - guid: fa15f9e67ebc54136be977a5f3dee634 type: 5 - m_fileInfoHash: 8683.prefab + m_fileInfoHash: 8776.prefab m_assetbundle: m_addressable: m_atlas: - m_fileSize: 8683 - m_assetChangeTS: 1770989093 - m_fileInfoReadTS: 1770989097 - m_fileWriteTS: 1770989093 - m_cachefileWriteTS: 1770989093 + m_fileSize: 8776 + m_assetChangeTS: 1777730506 + m_fileInfoReadTS: 1777730509 + m_fileWriteTS: 1777730505 + m_cachefileWriteTS: 1777730505 refreshStamp: 2 UseGUIDsList: - guid: fe87c0e1cc204ed48ad3b37840f39efc @@ -153489,15 +153489,15 @@ MonoBehaviour: UseGUIDsList: [] - guid: 1d40f46869fc84408ab4870b70e789ef type: 2 - m_fileInfoHash: 11550.cs + m_fileInfoHash: 11301.cs m_assetbundle: m_addressable: m_atlas: - m_fileSize: 11550 - m_assetChangeTS: 1774073753 - m_fileInfoReadTS: 1774073762 - m_fileWriteTS: 1774073750 - m_cachefileWriteTS: 1774073750 + m_fileSize: 11301 + m_assetChangeTS: 1777730330 + m_fileInfoReadTS: 1777730351 + m_fileWriteTS: 1777730027 + m_cachefileWriteTS: 1777730027 refreshStamp: 2 UseGUIDsList: [] - guid: 1d50f0545bfd1304eace331e06cb2cc2 @@ -232704,15 +232704,15 @@ MonoBehaviour: UseGUIDsList: [] - guid: d4dfe4d6abafce9449218211cb48dadb type: 2 - m_fileInfoHash: 5492.cs + m_fileInfoHash: 5333.cs m_assetbundle: m_addressable: m_atlas: - m_fileSize: 5492 - m_assetChangeTS: 1777724946 - m_fileInfoReadTS: 1777724975 - m_fileWriteTS: 1777724544 - m_cachefileWriteTS: 1777724544 + m_fileSize: 5333 + m_assetChangeTS: 1777730330 + m_fileInfoReadTS: 1777730351 + m_fileWriteTS: 1777730027 + m_cachefileWriteTS: 1777730027 refreshStamp: 2 UseGUIDsList: [] - guid: 5f068825cf8c22b4fa573d55654c2474 @@ -256515,36 +256515,36 @@ MonoBehaviour: m_addressable: m_atlas: m_fileSize: 1609448 - m_assetChangeTS: 1777724946 - m_fileInfoReadTS: 1777724975 - m_fileWriteTS: 1777724458 - m_cachefileWriteTS: 1777724458 + m_assetChangeTS: 1777729780 + m_fileInfoReadTS: 1777729801 + m_fileWriteTS: 1777729744 + m_cachefileWriteTS: 1777729744 refreshStamp: 2 UseGUIDsList: [] - guid: 5f95b2ad8cd26e0418cc0cdfc3750435 type: 9 - m_fileInfoHash: 1609445.json + m_fileInfoHash: 1609448.json m_assetbundle: m_addressable: m_atlas: - m_fileSize: 1609445 - m_assetChangeTS: 1777724946 - m_fileInfoReadTS: 1777724975 - m_fileWriteTS: 1777724146 - m_cachefileWriteTS: 1777724146 + m_fileSize: 1609448 + m_assetChangeTS: 1777729780 + m_fileInfoReadTS: 1777729801 + m_fileWriteTS: 1777729444 + m_cachefileWriteTS: 1777729444 refreshStamp: 2 UseGUIDsList: [] - guid: 986f04cde9c76b040832e51ebdc4dacd type: 9 - m_fileInfoHash: 1609494.json + m_fileInfoHash: 1609448.json m_assetbundle: m_addressable: m_atlas: - m_fileSize: 1609494 - m_assetChangeTS: 0 - m_fileInfoReadTS: 1777724975 - m_fileWriteTS: 1777724945 - m_cachefileWriteTS: 1777724945 + m_fileSize: 1609448 + m_assetChangeTS: 1777729780 + m_fileInfoReadTS: 1777729801 + m_fileWriteTS: 1777729144 + m_cachefileWriteTS: 1777729144 refreshStamp: 2 UseGUIDsList: [] setting: diff --git a/Assets/Prefabs/DynamicUI/Elements/Composite/AddNewButton.prefab b/Assets/Prefabs/DynamicUI/Elements/Composite/AddNewButton.prefab index a396f3c6..177f6484 100644 --- a/Assets/Prefabs/DynamicUI/Elements/Composite/AddNewButton.prefab +++ b/Assets/Prefabs/DynamicUI/Elements/Composite/AddNewButton.prefab @@ -213,10 +213,10 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 24 + m_fontSize: 35.8 m_fontSizeBase: 24 m_fontWeight: 400 - m_enableAutoSizing: 0 + m_enableAutoSizing: 1 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 0 @@ -224,20 +224,23 @@ MonoBehaviour: m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 + m_characterHorizontalScale: 1 m_wordSpacing: 0 m_lineSpacing: 0 m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 0 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} parentLinkedComponent: {fileID: 0} m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 diff --git a/Assets/Scenes/EditorScene.unity b/Assets/Scenes/EditorScene.unity index cf5219fc..93e6b0b7 100644 --- a/Assets/Scenes/EditorScene.unity +++ b/Assets/Scenes/EditorScene.unity @@ -155,8 +155,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 1} m_AnchorMax: {x: 0.5, y: 1} - m_AnchoredPosition: {x: -150, y: -221.305} - m_SizeDelta: {x: 400, y: 299.458} + m_AnchoredPosition: {x: -150, y: -80.91} + m_SizeDelta: {x: 400, y: 17.2} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &17246661 MonoBehaviour: @@ -9183,7 +9183,6 @@ MonoBehaviour: currentJudgeType: 0 useClickSelect: 0 useNotePrefab: 0 - ExpandWhileClick: 0 useQuickMove: 0 --- !u!114 &1197505593 MonoBehaviour: diff --git a/Assets/Scripts/DynamicUI/Hierarchy/Hierarchy.cs b/Assets/Scripts/DynamicUI/Hierarchy/Hierarchy.cs index 201394fc..e51c29c3 100644 --- a/Assets/Scripts/DynamicUI/Hierarchy/Hierarchy.cs +++ b/Assets/Scripts/DynamicUI/Hierarchy/Hierarchy.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; using DG.Tweening; +using Lean.Pool; using Ichni.RhythmGame; using Unity.VisualScripting; using UnityEngine; @@ -29,26 +30,23 @@ namespace Ichni.Editor rectTransform = this.GetComponent(); } - public HierarchyTab GenerateTab(GameElement targetElement, GameElement parentElement) + public HierarchyTab GenerateTab(GameElement targetElement, GameElement parentElement, bool animate = true) { - HierarchyTab tab = Instantiate(hierarchyTabPrefab, tabContainer).GetComponent(); - tab.SetTab(targetElement, parentElement); + if (targetElement.connectedTab != null) return targetElement.connectedTab; + + HierarchyTab tab = LeanPool.Spawn(hierarchyTabPrefab, tabContainer).GetComponent(); + tab.SetTab(targetElement, parentElement, animate); tabList.Add(tab); return tab; } public async Task GenerateTabAsync(GameElement targetElement, GameElement parentElement) { - var request = InstantiateAsync(hierarchyTabPrefab, tabContainer); + if (targetElement.connectedTab != null) return targetElement.connectedTab; - // 等待实例化过程完成 - while (!request.isDone) - { - await Task.Yield(); // 异步地等待下一帧 - } - HierarchyTab tab = request.Result[0].GetComponent(); + HierarchyTab tab = LeanPool.Spawn(hierarchyTabPrefab, tabContainer).GetComponent(); tab.SetTab(targetElement, parentElement); tabList.Add(tab); - // 返回实例化的游戏对象 + await Task.Yield(); return tab; } public bool isExpand = false; @@ -100,29 +98,20 @@ namespace Ichni.Editor { if (targetElement.connectedTab != null) { - // 如果已经有Tab了,直接选中 targetElement.connectedTab.SelectGameElement(); getTabPos(targetElement.connectedTab); return; } targetElement.ScanAndAddEnableTypes(); - if (!EditorManager.instance.ExpandWhileClick) - { - var tab = EditorManager.instance.uiManager.hierarchy.GenerateTab(targetElement, null); - tab.SelectGameElement(); - Destroy(tab.gameObject); - EditorManager.instance.uiManager.hierarchy.tabList.Remove(tab); - } - else - { - StartCoroutine(TryGetTab(targetElement)); - } + + StartCoroutine(TryGetTab(targetElement)); } + public IEnumerator TryGetTab(GameElement targetElement) { - // 1. 向上找到最近的有Tab的祖先 + // 1. 向上收集所有没有Tab的祖先 Stack stack = new Stack(); GameElement current = targetElement; while (current != null && current.connectedTab == null) @@ -131,47 +120,42 @@ namespace Ichni.Editor current = current.parentElement; } - // 2. 如果有Tab的祖先存在,依次展开回目标 - HierarchyTab parentTab = current != null ? current.connectedTab : null; + // 2. 从顶层祖先开始,逐层同步展开 while (stack.Count > 0) { var elem = stack.Pop(); - // 只展开父Tab,不直接生成Tab - if (elem.parentElement != null && elem.parentElement.connectedTab != null) - { - if (!elem.parentElement.connectedTab.isExpanded) - { - elem.parentElement.connectedTab.ExpandOrFold(true); - } - else if (!elem.parentElement.connectedTab.isExpandDone) - { - elem.parentElement.connectedTab.ExpandOrFold(); - elem.parentElement.connectedTab.ExpandOrFold(true);//合上再展开,这思路也是没谁了 - } - else - { - //他就在展开了,等下就好了 - } - yield return null; - } - // 等待当前elem的Tab生成 - while (elem.connectedTab == null) - { - yield return null; - } - parentTab = elem.connectedTab; - } - - // 3. 等待目标Tab实例化 - while (targetElement.connectedTab is null) - { + var parentTab = elem.parentElement?.connectedTab; + if (parentTab != null) + { + if (!parentTab.isExpanded) + { + StartCoroutine(parentTab.ExpandSyncBatched()); + yield return new WaitUntil(() => parentTab.isExpandDone); + } + else if (elem.connectedTab == null) + { + // 父节点已展开但当前元素缺失Tab(刚添加或曾被折叠),直接补生成 + GenerateTab(elem, elem.parentElement, false); + } + } + else + { + if (elem.connectedTab == null) + GenerateTab(elem, null, false); + } yield return null; } - yield return null; // 等待一帧,确保UI更新 + + // 3. 最终确保目标Tab存在 + if (targetElement.connectedTab == null) + { + GenerateTab(targetElement, targetElement.parentElement, false); + yield return null; + } + + yield return null; getTabPos(targetElement.connectedTab); - - } void getTabPos(HierarchyTab finalTab) { diff --git a/Assets/Scripts/DynamicUI/Hierarchy/HierarchyTab.cs b/Assets/Scripts/DynamicUI/Hierarchy/HierarchyTab.cs index 715d84a8..09894c2a 100644 --- a/Assets/Scripts/DynamicUI/Hierarchy/HierarchyTab.cs +++ b/Assets/Scripts/DynamicUI/Hierarchy/HierarchyTab.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using DG.Tweening; +using Lean.Pool; using Ichni.RhythmGame; using Michsky.MUIP; using Sirenix.Utilities; @@ -35,10 +36,20 @@ namespace Ichni.Editor public DoubleCheckButton deleteButton; public TMP_Text tabButtonText; - public void SetTab(GameElement targetElement, GameElement parentElement) + private List indentationLines = new List(); + + public void SetTab(GameElement targetElement, GameElement parentElement, bool animate = true) { - transform.localScale = Vector3.one; - transform.DOScale(Vector3.one, 0.2f).SetEase(Ease.OutCirc).From(new Vector3(1, 0, 1)); + if (animate) + { + transform.localScale = Vector3.one; + transform.DOScale(Vector3.one, 0.2f).SetEase(Ease.OutCirc).From(new Vector3(1, 0, 1)); + } + else + { + transform.DOKill(); + transform.localScale = Vector3.one; + } connectedGameElement = targetElement; tabButtonText.text = targetElement.elementName; targetElement.connectedTab = this; @@ -46,6 +57,14 @@ namespace Ichni.Editor this.isSelected = false; this.childTabList = new List(); + // 清除旧的缩进线 + for (int i = indentationLines.Count - 1; i >= 0; i--) + { + if (indentationLines[i] != null) + Destroy(indentationLines[i]); + } + indentationLines.Clear(); + if (parentElement == null) { this.tabLayer = 0; @@ -62,7 +81,10 @@ namespace Ichni.Editor if (!this.parentTab.isExpanded) { this.isExpanded = false; + var pt = this.parentTab; SetExpansion(false); + pt.SetStatus(); + return; } for (int i = 1; i <= this.tabLayer; i++) @@ -70,14 +92,17 @@ namespace Ichni.Editor float lineX = 30 * i - 15; var d = Instantiate(indentationLinePrefab, tabRect); d.GetComponent().anchoredPosition = new Vector2(lineX, 0); + indentationLines.Add(d); } - parentTab.SetStatus(); + parentTab?.SetStatus(); } float posX = (30 * tabLayer); tabMainRect.anchoredPosition = new Vector2(posX, tabMainRect.anchoredPosition.y); + tabButton.onClick.RemoveAllListeners(); tabButton.onClick.AddListener(SelectGameElement); + expandButton.onClick.RemoveAllListeners(); expandButton.onClick.AddListener(ExpandOrFold); deleteButton.onConfirm = () => EditorManager.instance.operationManager.CopyPasteDeleteModule.DeleteElement(connectedGameElement); @@ -87,6 +112,13 @@ namespace Ichni.Editor private void OnDestroy() { transform.DOKill(); + // 清除缩进线 + for (int i = indentationLines.Count - 1; i >= 0; i--) + { + if (indentationLines[i] != null) + Destroy(indentationLines[i]); + } + indentationLines.Clear(); } public void SetStatus() @@ -293,9 +325,6 @@ namespace Ichni.Editor connectedGameElement.ScanAndAddEnableTypes(); List FixedList = !forceAllExPand ? connectedGameElement.GetChildrenByTypes() : connectedGameElement.childElementList; - // float startTime = Time.realtimeSinceStartup; - // connectedGameElement.childElementList.Sort();//TODO: 后续可以让玩家手动快速排序 - Debug.Log(FixedList.Count); ExpandAsync(FixedList); } @@ -313,19 +342,57 @@ namespace Ichni.Editor { if (!expand && isExpanded) { - for (int i = childTabList.Count; i > 0; i--) + for (int i = childTabList.Count - 1; i >= 0; i--) { - childTabList[i - 1].SetExpansion(expand); //false + if (childTabList[i] != null) + childTabList[i].SetExpansion(expand); } } if (!expand) { - parentTab.childTabList.Remove(this); - Destroy(gameObject); - EditorManager.instance.uiManager.hierarchy.tabList.Remove(this); + CleanupAndDespawn(); } } + + private void CleanupAndDespawn() + { + if (connectedGameElement != null) + { + // 如果该元素还在选中列表中,先移除(须在 connectedTab=null 之前执行) + if (isSelected) + { + var sel = EditorManager.instance.operationManager.currentSelectedElements; + sel.Remove(connectedGameElement); + isSelected = false; + } + connectedGameElement.connectedTab = null; + } + + parentTab?.childTabList.Remove(this); + EditorManager.instance.uiManager.hierarchy.tabList.Remove(this); + + transform.DOKill(); + + tabButton.onClick.RemoveAllListeners(); + expandButton.onClick.RemoveAllListeners(); + + for (int i = indentationLines.Count - 1; i >= 0; i--) + { + if (indentationLines[i] != null) + Destroy(indentationLines[i]); + } + indentationLines.Clear(); + + connectedGameElement = null; + parentTab = null; + childTabList?.Clear(); + isExpanded = false; + isExpandDone = true; + tabLayer = 0; + + LeanPool.Despawn(gameObject); + } private void ExpandAnim() { expandButton.transform.DORotate(new Vector3(0, 0, !isExpanded ? 0f : 180f), 0.2f); @@ -341,12 +408,36 @@ namespace Ichni.Editor { var childElement = FixedList[index]; EditorManager.instance.uiManager.hierarchy.GenerateTab(childElement, connectedGameElement); - Debug.Log($"生成子Tab:{childElement.elementName},索引:{index},总数:{FixedList.Count}"); - - // 如果处理时间超过帧时间限制,直接继续执行而不等待 - // 移除了原来的 yield return null 等待逻辑 } } + public IEnumerator ExpandSyncBatched() + { + connectedGameElement.ScanAndAddEnableTypes(); + isExpanded = true; + isExpandDone = false; + ExpandAnim(); + + var children = connectedGameElement.childElementList; + int batchCount = 0; + for (int i = 0; i < children.Count; i++) + { + if (!isExpanded) break; + if (children[i].connectedTab == null) + { + EditorManager.instance.uiManager.hierarchy.GenerateTab(children[i], connectedGameElement, false); + batchCount++; + if (batchCount >= 15) + { + batchCount = 0; + yield return null; + if (!isExpanded) break; + } + } + } + + isExpandDone = true; + } + async void ExpandAsync(List FixedList) { isExpandDone = false; @@ -355,7 +446,6 @@ namespace Ichni.Editor var childElement = FixedList[index]; await EditorManager.instance.uiManager.hierarchy.GenerateTabAsync(childElement, connectedGameElement); - Debug.Log($"生成子Tab:{childElement.elementName},索引:{index},总数:{FixedList.Count}"); if (!isExpanded) break; } diff --git a/Assets/Scripts/DynamicUI/MainUI/ToolBar/ToolBar.cs b/Assets/Scripts/DynamicUI/MainUI/ToolBar/ToolBar.cs index 8a185a0b..48929e5e 100644 --- a/Assets/Scripts/DynamicUI/MainUI/ToolBar/ToolBar.cs +++ b/Assets/Scripts/DynamicUI/MainUI/ToolBar/ToolBar.cs @@ -94,7 +94,7 @@ namespace Ichni.Editor var item = LeanPool.Spawn(searchResultItemPrefab, searchResultsRoot); var itemText = item.GetComponentInChildren(); if (itemText != null) - itemText.text = element.elementName + " " + element.GetType().ToString(); + itemText.text = element.elementName + " | " + element.GetType().ToString(); var button = item.GetComponentInChildren