Files
ichni_Creator_Studio/Assets/Scripts/DynamicUI/Hierarchy/Hierarchy.cs

204 lines
8.1 KiB
C#
Raw Normal View History

2025-03-08 23:11:55 -05:00
using System;
2025-02-09 23:47:42 -05:00
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
2025-06-30 16:37:34 +08:00
using DG.Tweening;
using Lean.Pool;
2025-02-09 23:47:42 -05:00
using Ichni.RhythmGame;
using Unity.VisualScripting;
2025-02-09 23:47:42 -05:00
using UnityEngine;
using UnityEngine.UI;
2025-02-09 23:47:42 -05:00
namespace Ichni.Editor
{
public class Hierarchy : StaticWindow
{
public GameObject hierarchyTabPrefab;
public RectTransform tabContainer;
2025-03-08 23:11:55 -05:00
public Button addFolderButton;
2025-02-09 23:47:42 -05:00
public List<HierarchyTab> tabList;
2025-06-30 16:37:34 +08:00
public Button expandButtom;
public bool NeedExecute = false;
2025-03-08 23:11:55 -05:00
private void Awake()
{
tabList = new List<HierarchyTab>();
addFolderButton.onClick.AddListener(() =>
{
ElementFolder.GenerateElement("New Folder", Guid.NewGuid(), new List<string>(), true, null);
});
2025-06-30 16:37:34 +08:00
expandButtom.onClick.AddListener(Expand);
rectTransform = this.GetComponent<RectTransform>();
2025-03-08 23:11:55 -05:00
}
public HierarchyTab GenerateTab(GameElement targetElement, GameElement parentElement, bool animate = true)
2025-02-09 23:47:42 -05:00
{
if (targetElement.connectedTab != null) return targetElement.connectedTab;
HierarchyTab tab = LeanPool.Spawn(hierarchyTabPrefab, tabContainer).GetComponent<HierarchyTab>();
tab.SetTab(targetElement, parentElement, animate);
tabList.Add(tab);
return tab;
2025-02-09 23:47:42 -05:00
}
public async Task<HierarchyTab> GenerateTabAsync(GameElement targetElement, GameElement parentElement)
{
if (targetElement.connectedTab != null) return targetElement.connectedTab;
HierarchyTab tab = LeanPool.Spawn(hierarchyTabPrefab, tabContainer).GetComponent<HierarchyTab>();
tab.SetTab(targetElement, parentElement);
tabList.Add(tab);
await Task.Yield();
return tab;
}
2025-06-30 16:37:34 +08:00
public bool isExpand = false;
private RectTransform rectTransform;
public void Expand()
{
float originX = 225f;
isExpand = !isExpand;
// 用DOTween动画赋值
if (isExpand)
{
rectTransform.DOSizeDelta(
new Vector2(rectTransform.sizeDelta.x * 2, rectTransform.sizeDelta.y), 0.5f);
rectTransform.DOAnchorPos(
new Vector2(originX * 2, rectTransform.anchoredPosition.y), 0.5f);
enableButtonGroup.disableButton.GetComponent<RectTransform>().DOAnchorPos(
new Vector2(
enableButtonGroup.disableButton.GetComponent<RectTransform>().anchoredPosition.x * 3,
enableButtonGroup.disableButton.GetComponent<RectTransform>().anchoredPosition.y
), 0.5f);
expandButtom.GetComponent<RectTransform>().DOAnchorPos(
new Vector2(
expandButtom.GetComponent<RectTransform>().anchoredPosition.x * 2,
expandButtom.GetComponent<RectTransform>().anchoredPosition.y
), 0.5f);
}
else
{
rectTransform.DOSizeDelta(
new Vector2(rectTransform.sizeDelta.x / 2, rectTransform.sizeDelta.y), 0.5f);
rectTransform.DOAnchorPos(
new Vector2(originX, rectTransform.anchoredPosition.y), 0.5f);
enableButtonGroup.disableButton.GetComponent<RectTransform>().DOAnchorPos(
new Vector2(
enableButtonGroup.disableButton.GetComponent<RectTransform>().anchoredPosition.x / 3,
enableButtonGroup.disableButton.GetComponent<RectTransform>().anchoredPosition.y
), 0.5f);
expandButtom.GetComponent<RectTransform>().DOAnchorPos(
new Vector2(
expandButtom.GetComponent<RectTransform>().anchoredPosition.x / 2,
expandButtom.GetComponent<RectTransform>().anchoredPosition.y
), 0.5f);
}
}
2025-03-16 00:42:27 +08:00
2025-05-11 14:12:47 +08:00
public ScrollRect scrollRect;
public Vector2 vector2;
2025-06-29 21:28:49 +08:00
public void FindTab(GameElement targetElement)
{
if (targetElement.connectedTab != null)
{
targetElement.connectedTab.SelectGameElement();
getTabPos(targetElement.connectedTab);
return;
}
2025-06-29 21:28:49 +08:00
targetElement.ScanAndAddEnableTypes();
StartCoroutine(TryGetTab(targetElement));
2025-06-29 21:28:49 +08:00
2025-06-14 20:47:45 +08:00
}
2025-06-14 20:47:45 +08:00
public IEnumerator TryGetTab(GameElement targetElement)
{
// 1. 向上收集所有没有Tab的祖先
2025-06-14 20:47:45 +08:00
Stack<GameElement> stack = new Stack<GameElement>();
GameElement current = targetElement;
while (current != null && current.connectedTab == null)
{
2025-06-14 20:47:45 +08:00
stack.Push(current);
current = current.parentElement;
}
2025-06-14 20:47:45 +08:00
// 2. 从顶层祖先开始,逐层同步展开
2025-06-14 20:47:45 +08:00
while (stack.Count > 0)
{
2025-06-14 20:47:45 +08:00
var elem = stack.Pop();
var parentTab = elem.parentElement?.connectedTab;
if (parentTab != null)
2025-05-24 14:34:12 +08:00
{
if (!parentTab.isExpanded)
{
StartCoroutine(parentTab.ExpandSyncBatched());
yield return new WaitUntil(() => parentTab.isExpandDone);
}
else if (elem.connectedTab == null)
{
// 父节点已展开但当前元素缺失Tab刚添加或曾被折叠直接补生成
GenerateTab(elem, elem.parentElement, false);
}
2025-05-24 14:34:12 +08:00
}
else
2025-05-24 14:34:12 +08:00
{
if (elem.connectedTab == null)
GenerateTab(elem, null, false);
2025-05-24 14:34:12 +08:00
}
yield return null;
2025-06-14 20:47:45 +08:00
}
2025-05-24 14:34:12 +08:00
// 3. 最终确保目标Tab存在
if (targetElement.connectedTab == null)
2025-06-14 20:47:45 +08:00
{
GenerateTab(targetElement, targetElement.parentElement, false);
2025-06-14 20:47:45 +08:00
yield return null;
}
yield return null;
getTabPos(targetElement.connectedTab);
}
void getTabPos(HierarchyTab finalTab)
{
// 修正定位算法
RectTransform tabRect = finalTab.GetComponent<RectTransform>();
RectTransform containerRect = tabContainer;
RectTransform viewportRect = scrollRect.viewport != null ? scrollRect.viewport : scrollRect.GetComponent<RectTransform>();
// Tab相对于内容顶部的距离正值为下负值为上
float tabTop = -tabRect.anchoredPosition.y;
float tabHeight = tabRect.rect.height;
float contentHeight = containerRect.rect.height;
float viewportHeight = viewportRect.rect.height;
// 目标让Tab居中或尽量居中
float targetCenter = tabTop + tabHeight / 2f;
float viewportCenter = viewportHeight / 2f;
float scrollOffset = targetCenter - viewportCenter;
// normalizedPosition = 1 - (scrollOffset / (contentHeight - viewportHeight))
float denominator = Mathf.Max(1f, contentHeight - viewportHeight);
float normalized = 1f - Mathf.Clamp01(scrollOffset / denominator);
scrollRect.verticalNormalizedPosition = normalized;
2025-06-14 20:47:45 +08:00
finalTab.SelectGameElement();
2025-06-29 21:28:49 +08:00
}
public GameElement upLoadElement = null;
public IEnumerator TryGetElement()
{
NeedExecute = true;
// 等待直到upLoadElement被赋值
if (upLoadElement == null)
{
yield return new WaitUntil(() => upLoadElement != null);
}
NeedExecute = false;
upLoadElement = null;
}
2025-02-09 23:47:42 -05:00
}
}