Files
bansonic_beta_main/Assets/scripts/selectYourSongFirst/UI_SelectSong_EnterAnim.cs
T

365 lines
11 KiB
C#

using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
public class UI_SelectSong_EnterAnim : MonoBehaviour
{
[Header("Play")]
[SerializeField] bool playOnEnable = true;
[SerializeField] float delay = 0.05f;
[Header("Timing")]
[SerializeField] float panelTime = 0.55f;
[SerializeField] float titleTime = 0.4f;
[SerializeField] float listTime = 0.55f;
[SerializeField] float buttonTime = 0.35f;
[SerializeField] float stagger = 0.06f;
[SerializeField] Ease ease = Ease.OutCubic;
[Header("Offsets")]
[SerializeField] float slideX = 180f;
[SerializeField] float slideY = 120f;
[SerializeField] float bgScaleFrom = 1.06f;
[SerializeField] bool useUnscaledTime = true;
[SerializeField] bool ensureVisibleOnComplete = true;
RectTransform root;
RectTransform bg;
RectTransform leftDlc;
RectTransform songScroll;
RectTransform rightInfos;
RectTransform songTitle;
RectTransform dlcTitle;
RectTransform quickEnter;
RectTransform enterDetail;
RectTransform difficultyGroup;
readonly Dictionary<RectTransform, Vector2> basePos = new();
readonly Dictionary<RectTransform, Vector3> baseScale = new();
readonly List<RectTransform> difficultyItems = new();
Sequence enterSeq;
void Awake()
{
CacheRefs();
}
void OnEnable()
{
if (playOnEnable)
{
Play();
}
}
public void Play()
{
CacheRefs();
KillTweens();
Prepare();
BuildSequence();
}
public void SetDelay(float value)
{
delay = Mathf.Max(0f, value);
}
void CacheRefs()
{
if (root == null)
{
root = transform.parent as RectTransform;
if (root == null)
{
Canvas canvas = Object.FindAnyObjectByType<Canvas>();
if (canvas != null)
{
root = canvas.transform as RectTransform;
}
}
}
if (root == null)
{
return;
}
bg = bg != null ? bg : FindPreferredSelectSceneBg();
leftDlc = leftDlc != null ? leftDlc : FindRect(root, "left_select_dlc");
songScroll = songScroll != null ? songScroll : FindRect(root, "SongScrollView");
rightInfos = rightInfos != null ? rightInfos : FindRect(root, "rightInfos");
songTitle = songTitle != null ? songTitle : FindRect(root, "songSVtitle");
dlcTitle = dlcTitle != null ? dlcTitle : FindRect(root, "dlcSVtitle");
quickEnter = quickEnter != null ? quickEnter : FindRect(root, "quickEnterThisSong");
enterDetail = enterDetail != null ? enterDetail : FindRect(root, "enter detail page");
difficultyGroup = difficultyGroup != null ? difficultyGroup : FindRect(root, "difficultyBtnInfos");
difficultyItems.Clear();
if (difficultyGroup != null)
{
for (int i = 0; i < difficultyGroup.childCount; i++)
{
RectTransform child = difficultyGroup.GetChild(i) as RectTransform;
if (child != null)
{
difficultyItems.Add(child);
}
}
difficultyItems.Sort((a, b) => a.anchoredPosition.x.CompareTo(b.anchoredPosition.x));
}
}
RectTransform FindRect(Transform rootTransform, string name)
{
if (rootTransform == null || string.IsNullOrEmpty(name))
{
return null;
}
Transform direct = rootTransform.Find(name);
if (direct != null)
{
return direct as RectTransform;
}
RectTransform[] rects = rootTransform.GetComponentsInChildren<RectTransform>(true);
for (int i = 0; i < rects.Length; i++)
{
if (rects[i] != null && rects[i].name == name)
{
return rects[i];
}
}
return null;
}
RectTransform FindPreferredSelectSceneBg()
{
// Prefer the scene root object named "bg" that owns a Canvas
// (the one shown in your hierarchy screenshot), not the legacy inactive "BG".
Transform[] all = Resources.FindObjectsOfTypeAll<Transform>();
for (int i = 0; i < all.Length; i++)
{
Transform t = all[i];
if (t == null) continue;
GameObject go = t.gameObject;
if (go == null || !go.scene.IsValid()) continue;
if (!string.Equals(t.name, "bg", System.StringComparison.OrdinalIgnoreCase)) continue;
if (go.GetComponent<Canvas>() == null) continue;
return t as RectTransform;
}
// Fallbacks for older scene hierarchy.
RectTransform fallback = FindRect(root, "BG");
if (fallback != null) return fallback;
return FindRect(root, "bg");
}
void CacheBase(RectTransform rect)
{
if (rect == null)
{
return;
}
if (!basePos.ContainsKey(rect))
{
basePos[rect] = rect.anchoredPosition;
}
if (!baseScale.ContainsKey(rect))
{
baseScale[rect] = rect.localScale;
}
}
void Prepare()
{
if (bg != null && bg.gameObject.activeInHierarchy)
{
CacheBase(bg);
bg.localScale = baseScale[bg] * bgScaleFrom;
CanvasGroup group = EnsureCanvasGroup(bg);
if (group != null) group.alpha = 0f;
}
PrepareSlide(leftDlc, Vector2.left * slideX);
PrepareSlide(songScroll, Vector2.down * slideY);
PrepareSlide(rightInfos, Vector2.right * slideX);
PrepareSlide(songTitle, Vector2.up * (slideY * 0.6f));
PrepareSlide(dlcTitle, Vector2.left * (slideX * 0.6f));
PrepareScale(quickEnter, 0.92f);
PrepareScale(enterDetail, 0.92f);
for (int i = 0; i < difficultyItems.Count; i++)
{
PrepareSlide(difficultyItems[i], Vector2.down * (slideY * 0.35f));
}
}
void PrepareSlide(RectTransform rect, Vector2 offset)
{
if (rect == null)
{
return;
}
CacheBase(rect);
rect.anchoredPosition = basePos[rect] + offset;
CanvasGroup group = EnsureCanvasGroup(rect);
if (group != null) group.alpha = 0f;
}
void PrepareScale(RectTransform rect, float scaleMul)
{
if (rect == null)
{
return;
}
CacheBase(rect);
rect.localScale = baseScale[rect] * scaleMul;
CanvasGroup group = EnsureCanvasGroup(rect);
if (group != null) group.alpha = 0f;
}
void BuildSequence()
{
enterSeq = DOTween.Sequence().SetUpdate(useUnscaledTime);
float t = delay;
if (bg != null && bg.gameObject.activeInHierarchy)
{
CanvasGroup group = EnsureCanvasGroup(bg);
if (group != null)
{
enterSeq.Insert(t, group.DOFade(1f, panelTime).SetEase(ease).SetUpdate(useUnscaledTime));
}
if (baseScale.TryGetValue(bg, out Vector3 scale))
{
enterSeq.Insert(t, bg.DOScale(scale, panelTime).SetEase(ease).SetUpdate(useUnscaledTime));
}
}
InsertSlide(leftDlc, t + 0.05f, panelTime);
InsertSlide(dlcTitle, t + 0.08f, titleTime);
InsertSlide(songTitle, t + 0.1f, titleTime);
InsertSlide(songScroll, t + 0.12f, listTime);
InsertSlide(rightInfos, t + 0.15f, panelTime);
if (difficultyItems.Count > 0)
{
float start = t + 0.25f;
for (int i = 0; i < difficultyItems.Count; i++)
{
InsertSlide(difficultyItems[i], start + i * stagger, buttonTime);
}
}
InsertScale(enterDetail, t + 0.35f, buttonTime);
InsertScale(quickEnter, t + 0.38f, buttonTime);
if (ensureVisibleOnComplete)
{
enterSeq.OnComplete(SnapAllToVisibleFinalState);
}
}
void InsertSlide(RectTransform rect, float at, float time)
{
if (rect == null)
{
return;
}
CacheBase(rect);
if (basePos.TryGetValue(rect, out Vector2 pos))
{
enterSeq.Insert(at, rect.DOAnchorPos(pos, time).SetEase(ease).SetUpdate(useUnscaledTime));
}
CanvasGroup group = EnsureCanvasGroup(rect);
if (group != null)
{
enterSeq.Insert(at, group.DOFade(1f, time).SetEase(ease).SetUpdate(useUnscaledTime));
}
}
void InsertScale(RectTransform rect, float at, float time)
{
if (rect == null)
{
return;
}
CacheBase(rect);
if (baseScale.TryGetValue(rect, out Vector3 scale))
{
enterSeq.Insert(at, rect.DOScale(scale, time).SetEase(ease).SetUpdate(useUnscaledTime));
}
CanvasGroup group = EnsureCanvasGroup(rect);
if (group != null)
{
enterSeq.Insert(at, group.DOFade(1f, time).SetEase(ease).SetUpdate(useUnscaledTime));
}
}
void SnapAllToVisibleFinalState()
{
SnapVisible(bg, applyScale: true);
SnapVisible(leftDlc, applyScale: false);
SnapVisible(songScroll, applyScale: false);
SnapVisible(rightInfos, applyScale: false);
SnapVisible(songTitle, applyScale: false);
SnapVisible(dlcTitle, applyScale: false);
SnapVisible(quickEnter, applyScale: true);
SnapVisible(enterDetail, applyScale: true);
for (int i = 0; i < difficultyItems.Count; i++)
{
SnapVisible(difficultyItems[i], applyScale: false);
}
}
void SnapVisible(RectTransform rect, bool applyScale)
{
if (rect == null) return;
if (!rect.gameObject.activeSelf) rect.gameObject.SetActive(true);
CacheBase(rect);
if (basePos.TryGetValue(rect, out Vector2 pos))
{
rect.anchoredPosition = pos;
}
if (applyScale && baseScale.TryGetValue(rect, out Vector3 scale))
{
rect.localScale = scale;
}
CanvasGroup group = EnsureCanvasGroup(rect);
if (group != null)
{
group.alpha = 1f;
group.interactable = true;
group.blocksRaycasts = true;
}
}
CanvasGroup EnsureCanvasGroup(RectTransform rect)
{
if (rect == null)
{
return null;
}
CanvasGroup group = rect.GetComponent<CanvasGroup>();
if (group == null)
{
group = rect.gameObject.AddComponent<CanvasGroup>();
}
return group;
}
void KillTweens()
{
if (enterSeq != null)
{
enterSeq.Kill();
enterSeq = null;
}
}
}