Files
bansonic_beta_main/Assets/scripts/UI/UI_OrderedEntryAnimator.cs
T

181 lines
6.2 KiB
C#

using System;
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
public static class UI_OrderedEntryAnimator
{
public static Sequence Play(
Transform root,
float itemDuration,
float itemStagger,
Vector2 fromOffset,
bool useUnscaledTime,
Predicate<RectTransform> includePredicate = null)
{
if (root == null) return null;
List<RectTransform> targets = CollectTargets(root, includePredicate);
if (targets.Count == 0) return null;
targets.Sort(CompareByTopThenLeft);
float duration = Mathf.Max(0.01f, itemDuration);
float stagger = Mathf.Max(0f, itemStagger);
Sequence sequence = DOTween.Sequence().SetUpdate(useUnscaledTime);
for (int i = 0; i < targets.Count; i++)
{
RectTransform rt = targets[i];
if (rt == null || !rt.gameObject.activeInHierarchy) continue;
CanvasGroup group = rt.GetComponent<CanvasGroup>();
if (group == null) group = rt.gameObject.AddComponent<CanvasGroup>();
rt.DOKill();
group.DOKill();
Vector2 basePos = rt.anchoredPosition;
float baseAlpha = group.alpha <= 0f ? 1f : group.alpha;
rt.anchoredPosition = basePos + fromOffset;
group.alpha = 0f;
float startAt = i * stagger;
sequence.Insert(startAt, rt.DOAnchorPos(basePos, duration).SetEase(Ease.OutCubic).SetUpdate(useUnscaledTime));
sequence.Insert(startAt, group.DOFade(baseAlpha, duration).SetEase(Ease.OutCubic).SetUpdate(useUnscaledTime));
}
return sequence;
}
public static Sequence PlayKeyDownFlash(
Transform keyDownRoot,
bool useUnscaledTime,
float fromYOffset = 36f,
float itemStagger = 0.03f)
{
if (keyDownRoot == null) return null;
List<RectTransform> targets = CollectKeyDownRects(keyDownRoot);
if (targets.Count == 0) return null;
targets.Sort(CompareByTopThenLeft);
Sequence sequence = DOTween.Sequence().SetUpdate(useUnscaledTime);
float moveDuration = 0.1f;
float stagger = Mathf.Max(0f, itemStagger);
float offsetY = Mathf.Abs(fromYOffset);
for (int i = 0; i < targets.Count; i++)
{
RectTransform rt = targets[i];
if (rt == null || !rt.gameObject.activeInHierarchy) continue;
CanvasGroup group = rt.GetComponent<CanvasGroup>();
if (group == null) group = rt.gameObject.AddComponent<CanvasGroup>();
rt.DOKill();
group.DOKill();
Vector2 basePos = rt.anchoredPosition;
rt.anchoredPosition = basePos - new Vector2(0f, offsetY);
group.alpha = 0f;
float startAt = i * stagger;
sequence.Insert(startAt, rt.DOAnchorPos(basePos, moveDuration).SetEase(Ease.OutCubic).SetUpdate(useUnscaledTime));
sequence.Insert(startAt, group.DOFade(1f, 0.028f).SetEase(Ease.Linear).SetUpdate(useUnscaledTime));
sequence.Insert(startAt + 0.028f, group.DOFade(0.2f, 0.026f).SetEase(Ease.Linear).SetUpdate(useUnscaledTime));
sequence.Insert(startAt + 0.054f, group.DOFade(1f, 0.04f).SetEase(Ease.OutCubic).SetUpdate(useUnscaledTime));
}
return sequence;
}
public static bool IsNamedOrChildOf(Transform target, string name)
{
if (target == null || string.IsNullOrEmpty(name)) return false;
Transform it = target;
while (it != null)
{
if (string.Equals(it.name, name, StringComparison.OrdinalIgnoreCase))
return true;
it = it.parent;
}
return false;
}
private static List<RectTransform> CollectTargets(Transform root, Predicate<RectTransform> includePredicate)
{
List<RectTransform> list = new List<RectTransform>(128);
HashSet<RectTransform> seen = new HashSet<RectTransform>();
Stack<Transform> stack = new Stack<Transform>();
stack.Push(root);
while (stack.Count > 0)
{
Transform parent = stack.Pop();
if (parent == null) continue;
for (int i = 0; i < parent.childCount; i++)
{
Transform child = parent.GetChild(i);
if (child == null) continue;
stack.Push(child);
RectTransform rt = child as RectTransform;
if (rt == null || !child.gameObject.activeInHierarchy) continue;
if (includePredicate != null && !includePredicate(rt)) continue;
if (!IsPanelLike(child)) continue;
if (!seen.Add(rt)) continue;
list.Add(rt);
}
}
return list;
}
private static List<RectTransform> CollectKeyDownRects(Transform root)
{
List<RectTransform> list = new List<RectTransform>(16);
RectTransform[] all = root.GetComponentsInChildren<RectTransform>(true);
for (int i = 0; i < all.Length; i++)
{
RectTransform rt = all[i];
if (rt == null || !rt.gameObject.activeInHierarchy) continue;
if (rt == root) continue;
string n = rt.name ?? string.Empty;
if (n.IndexOf("sdw 3", StringComparison.OrdinalIgnoreCase) < 0) continue;
list.Add(rt);
}
return list;
}
private static bool IsPanelLike(Transform tr)
{
if (tr == null) return false;
if (tr.GetComponent<Selectable>() != null) return true;
if (tr.GetComponent<Graphic>() != null) return true;
if (tr.GetComponent<LayoutGroup>() != null) return true;
if (tr.GetComponent<CanvasGroup>() != null) return true;
return tr.childCount > 0;
}
private static int CompareByTopThenLeft(RectTransform a, RectTransform b)
{
if (a == null && b == null) return 0;
if (a == null) return 1;
if (b == null) return -1;
Vector3 pa = a.position;
Vector3 pb = b.position;
int xOrder = pa.x.CompareTo(pb.x); // left -> right
if (xOrder != 0) return xOrder;
return -pa.y.CompareTo(pb.y); // top -> bottom
}
}