374 lines
11 KiB
C#
374 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 = SceneObjectLookupCache.FindAny<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 && child.gameObject.activeSelf)
|
|
{
|
|
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);
|
|
if (!UI_OrderedEntryAnimator.IsLayoutSensitive(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);
|
|
if (!UI_OrderedEntryAnimator.IsLayoutSensitive(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);
|
|
bool layoutSensitive = UI_OrderedEntryAnimator.IsLayoutSensitive(rect);
|
|
if (!layoutSensitive && 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);
|
|
bool layoutSensitive = UI_OrderedEntryAnimator.IsLayoutSensitive(rect);
|
|
if (!layoutSensitive && 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) return;
|
|
|
|
CacheBase(rect);
|
|
bool layoutSensitive = UI_OrderedEntryAnimator.IsLayoutSensitive(rect);
|
|
if (!layoutSensitive && basePos.TryGetValue(rect, out Vector2 pos))
|
|
{
|
|
rect.anchoredPosition = pos;
|
|
}
|
|
|
|
if (!layoutSensitive && 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;
|
|
}
|
|
}
|
|
}
|