176 lines
7.4 KiB
C#
176 lines
7.4 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using DG.Tweening;
|
||
using Ichni.RhythmGame;
|
||
using Unity.VisualScripting;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
namespace Ichni.Editor
|
||
{
|
||
public class Hierarchy : StaticWindow
|
||
{
|
||
public GameObject hierarchyTabPrefab;
|
||
public RectTransform tabContainer;
|
||
public Button addFolderButton;
|
||
public List<HierarchyTab> tabList;
|
||
public Button expandButtom;
|
||
private void Awake()
|
||
{
|
||
tabList = new List<HierarchyTab>();
|
||
addFolderButton.onClick.AddListener(() =>
|
||
{
|
||
ElementFolder.GenerateElement("New Folder", Guid.NewGuid(), new List<string>(), true, null);
|
||
});
|
||
expandButtom.onClick.AddListener(Expand);
|
||
rectTransform = this.GetComponent<RectTransform>();
|
||
}
|
||
|
||
public HierarchyTab GenerateTab(GameElement targetElement, GameElement parentElement)
|
||
{
|
||
HierarchyTab tab = Instantiate(hierarchyTabPrefab, tabContainer).GetComponent<HierarchyTab>();
|
||
tab.SetTab(targetElement, parentElement);
|
||
tabList.Add(tab);
|
||
return tab;
|
||
}
|
||
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);
|
||
}
|
||
}
|
||
|
||
public ScrollRect scrollRect;
|
||
public Vector2 vector2;
|
||
public void FindTab(GameElement targetElement)
|
||
{
|
||
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));
|
||
}
|
||
|
||
}
|
||
public IEnumerator TryGetTab(GameElement targetElement)
|
||
{
|
||
// 1. 向上找到最近的有Tab的祖先
|
||
Stack<GameElement> stack = new Stack<GameElement>();
|
||
GameElement current = targetElement;
|
||
while (current != null && current.connectedTab == null)
|
||
{
|
||
stack.Push(current);
|
||
current = current.parentElement;
|
||
}
|
||
|
||
// 2. 如果有Tab的祖先存在,依次展开回目标
|
||
HierarchyTab parentTab = current != null ? current.connectedTab : null;
|
||
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.ienumerator is null)
|
||
{
|
||
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)
|
||
{
|
||
|
||
yield return null;
|
||
}
|
||
|
||
HierarchyTab finalTab = targetElement.connectedTab;
|
||
|
||
// 修正定位算法
|
||
yield return null; // 等待布局刷新
|
||
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;
|
||
finalTab.SelectGameElement();
|
||
}
|
||
|
||
}
|
||
} |