技能主要更新,修复卡顿并加入动画,以及各种其他更新。
This commit is contained in:
@@ -0,0 +1,941 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
using UnityEngine.SceneManagement;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
[ExecuteAlways]
|
||||
public class BgmUiBinder : MonoBehaviour
|
||||
{
|
||||
public static BgmUiBinder Instance { get; private set; }
|
||||
[Header("Lookup Names")]
|
||||
public string musicRootName = "MusicPic";
|
||||
public string timeRootName = "TIME";
|
||||
public string progressName = "BGM_Progress";
|
||||
public string pointerName = "Zhizhen";
|
||||
public string spectrumRootName = "SpectrumRoot";
|
||||
public string musicPicCanvasName = "MusicPicCanvas";
|
||||
|
||||
[Header("Buttons")]
|
||||
public string prevButtonName = "Previous_Song";
|
||||
public string nextButtonName = "Next_Song";
|
||||
public string pauseButtonName = "pause_Song";
|
||||
public string musicToggleButtonName = "Button_Music";
|
||||
public Button prevButton;
|
||||
public Button nextButton;
|
||||
public Button pauseButton;
|
||||
public Button musicToggleButton;
|
||||
public bool useManualMusicToggle = true;
|
||||
public bool bindMusicToggleButton = false;
|
||||
|
||||
[Header("Bindings (optional)")]
|
||||
public Image progressImage;
|
||||
public Slider progressSlider;
|
||||
|
||||
public TMP_Text timeTmp;
|
||||
public Text timeText;
|
||||
public RectTransform pointerRect;
|
||||
public Vector2 pointerOffset = Vector2.zero;
|
||||
public bool enableMusicPicGyro = false;
|
||||
|
||||
[Header("MusicPic Toggle")]
|
||||
public bool keepMusicPicAcrossScenes = false;
|
||||
public bool showMusicPicInLobby = false;
|
||||
public bool forceHideOnSceneLoad = true;
|
||||
public string lobbySceneName = "UI_UI";
|
||||
public string gameplaySceneName = "gamePlay_gamePlay";
|
||||
public float musicPicFadeDuration = 0.3f;
|
||||
public bool useUnscaledTime = true;
|
||||
|
||||
[Header("Auto Create")]
|
||||
public bool autoCreateProgress = false;
|
||||
public Vector2 defaultProgressSize = new Vector2(320f, 8f);
|
||||
public Vector2 defaultProgressPosition = Vector2.zero;
|
||||
public Color progressColor = Color.white;
|
||||
public Vector2 pointerStartPos = new Vector2(-190.98f, -87.05f);
|
||||
public Vector2 pointerEndPos = new Vector2(195.3f, -87.05f);
|
||||
public Vector2 spectrumPosition = new Vector2(-238.9f, -111.5f);
|
||||
|
||||
private readonly List<TMP_Text> timeTmps = new List<TMP_Text>();
|
||||
private readonly List<Text> timeTexts = new List<Text>();
|
||||
|
||||
private System.Text.StringBuilder _sb = new System.Text.StringBuilder(32);
|
||||
private int _lastSeconds = -1;
|
||||
private int _lastTotalSeconds = -1;
|
||||
|
||||
private RectTransform musicRoot;
|
||||
private bool hasExplicitMusicRoot = false;
|
||||
private RectTransform progressRect;
|
||||
private float pointerBaseY = 0f;
|
||||
private bool musicPicVisible = true;
|
||||
private Coroutine musicPicTween;
|
||||
private Coroutine lobbyShowRoutine;
|
||||
private CanvasGroup musicPicGroup;
|
||||
private RectTransform spectrumRoot;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
private string _cachedGameplaySceneName;
|
||||
private bool _isGameplayScene;
|
||||
private bool _spectrumHiddenInGameplay = false;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
_cachedGameplaySceneName = gameplaySceneName;
|
||||
_isGameplayScene = SceneManager.GetActiveScene().name == _cachedGameplaySceneName;
|
||||
_spectrumHiddenInGameplay = false;
|
||||
_buttonsBound = false;
|
||||
Bind();
|
||||
ApplyDefaultMusicPicVisibility(SceneManager.GetActiveScene().name);
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
var mgr = BgmPlaybackManager.EnsureInstance();
|
||||
mgr.EnsurePlaying();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
}
|
||||
|
||||
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||
{
|
||||
_isGameplayScene = scene.name == _cachedGameplaySceneName;
|
||||
_spectrumHiddenInGameplay = false;
|
||||
_buttonsBound = false;
|
||||
Bind();
|
||||
ApplyDefaultMusicPicVisibility(scene.name);
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
musicRoot = null;
|
||||
hasExplicitMusicRoot = false;
|
||||
|
||||
Canvas sceneCanvas = FindSceneCanvas();
|
||||
var controller = Object.FindAnyObjectByType<btmandtopController>();
|
||||
if (controller != null && controller.musicPicRoot != null)
|
||||
{
|
||||
SetMusicRoot(controller.musicPicRoot, sceneCanvas);
|
||||
return;
|
||||
}
|
||||
RectTransform persistentMusic = null;
|
||||
var persistentCanvasGo = GameObject.Find(musicPicCanvasName);
|
||||
if (!keepMusicPicAcrossScenes && persistentCanvasGo != null)
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
Destroy(persistentCanvasGo);
|
||||
else
|
||||
DestroyImmediate(persistentCanvasGo);
|
||||
persistentCanvasGo = null;
|
||||
}
|
||||
if (persistentCanvasGo != null)
|
||||
{
|
||||
var candidate = persistentCanvasGo.transform.Find(musicRootName);
|
||||
if (candidate != null)
|
||||
persistentMusic = candidate as RectTransform;
|
||||
}
|
||||
|
||||
var candidates = FindAllMusicPic();
|
||||
RectTransform sceneMusic = null;
|
||||
var activeScene = SceneManager.GetActiveScene();
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
var c = candidates[i];
|
||||
if (c == null || c.gameObject.scene != activeScene)
|
||||
continue;
|
||||
if (sceneMusic == null)
|
||||
sceneMusic = c;
|
||||
if (c.GetComponentInParent<btmandtopController>(true) != null)
|
||||
{
|
||||
sceneMusic = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (persistentMusic != null)
|
||||
musicRoot = persistentMusic;
|
||||
else
|
||||
musicRoot = sceneMusic;
|
||||
|
||||
hasExplicitMusicRoot = musicRoot != null;
|
||||
|
||||
if (candidates.Count > 1)
|
||||
{
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
var c = candidates[i];
|
||||
if (c == null) continue;
|
||||
if (c == musicRoot) continue;
|
||||
if (Application.isPlaying)
|
||||
Destroy(c.gameObject);
|
||||
else
|
||||
DestroyImmediate(c.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
if (musicRoot == null)
|
||||
{
|
||||
var canvas = Object.FindAnyObjectByType<Canvas>();
|
||||
if (canvas != null)
|
||||
musicRoot = canvas.GetComponent<RectTransform>();
|
||||
}
|
||||
|
||||
if (hasExplicitMusicRoot)
|
||||
{
|
||||
EnsureMusicPicCanvas(sceneCanvas);
|
||||
EnsureMusicPicCanvasGroup();
|
||||
if (Application.isPlaying && forceHideOnSceneLoad)
|
||||
SetMusicPicVisible(false, true);
|
||||
}
|
||||
|
||||
if (progressSlider == null && progressImage == null)
|
||||
{
|
||||
if (musicRoot != null)
|
||||
{
|
||||
var target = musicRoot.Find(progressName);
|
||||
if (target != null)
|
||||
{
|
||||
progressSlider = target.GetComponent<Slider>();
|
||||
progressImage = target.GetComponent<Image>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (autoCreateProgress && progressSlider == null && progressImage == null && musicRoot != null)
|
||||
{
|
||||
var go = new GameObject(progressName, typeof(RectTransform), typeof(Image));
|
||||
var rt = go.GetComponent<RectTransform>();
|
||||
rt.SetParent(musicRoot, false);
|
||||
rt.sizeDelta = defaultProgressSize;
|
||||
rt.anchoredPosition = defaultProgressPosition;
|
||||
var img = go.GetComponent<Image>();
|
||||
img.type = Image.Type.Filled;
|
||||
img.fillMethod = Image.FillMethod.Horizontal;
|
||||
img.fillOrigin = 0;
|
||||
img.fillAmount = 0f;
|
||||
img.color = progressColor;
|
||||
progressImage = img;
|
||||
}
|
||||
|
||||
// If a progress bar exists outside MusicPic, ignore it and let cleanup remove it.
|
||||
if (musicRoot != null)
|
||||
{
|
||||
if (progressSlider != null && !progressSlider.transform.IsChildOf(musicRoot))
|
||||
progressSlider = null;
|
||||
if (progressImage != null && !progressImage.transform.IsChildOf(musicRoot))
|
||||
progressImage = null;
|
||||
}
|
||||
|
||||
// Cleanup any BGM_Progress that isn't under MusicPic
|
||||
CleanupProgressOutsideMusicRoot();
|
||||
|
||||
progressRect = null;
|
||||
if (progressSlider != null) progressRect = progressSlider.GetComponent<RectTransform>();
|
||||
if (progressRect == null && progressImage != null) progressRect = progressImage.rectTransform;
|
||||
|
||||
if (pointerRect == null)
|
||||
{
|
||||
Transform pointer = null;
|
||||
if (musicRoot != null)
|
||||
pointer = musicRoot.Find(pointerName);
|
||||
if (pointer == null)
|
||||
{
|
||||
var go = FindByNameContains(pointerName);
|
||||
if (go != null) pointer = go.transform;
|
||||
}
|
||||
if (pointer != null)
|
||||
pointerRect = pointer.GetComponent<RectTransform>();
|
||||
}
|
||||
if (pointerRect != null)
|
||||
{
|
||||
pointerBaseY = pointerRect.anchoredPosition.y;
|
||||
pointerRect.anchoredPosition = pointerStartPos;
|
||||
pointerBaseY = pointerStartPos.y;
|
||||
}
|
||||
|
||||
if (enableMusicPicGyro && musicRoot != null)
|
||||
{
|
||||
var gyro = musicRoot.GetComponent<BgmGyroRotator>();
|
||||
if (gyro == null) gyro = musicRoot.gameObject.AddComponent<BgmGyroRotator>();
|
||||
gyro.target = musicRoot;
|
||||
}
|
||||
|
||||
BindButtons();
|
||||
EnsureSpectrum();
|
||||
CacheTimeTargets();
|
||||
HideSpectrumInGameplay(SceneManager.GetActiveScene().name);
|
||||
}
|
||||
|
||||
public void SetMusicRoot(RectTransform root, Canvas sceneCanvas = null)
|
||||
{
|
||||
musicRoot = root;
|
||||
hasExplicitMusicRoot = musicRoot != null;
|
||||
if (!hasExplicitMusicRoot)
|
||||
return;
|
||||
EnsureMusicPicCanvas(sceneCanvas);
|
||||
EnsureMusicPicCanvasGroup();
|
||||
EnsureSpectrum();
|
||||
CacheTimeTargets();
|
||||
}
|
||||
|
||||
private void CacheTimeTargets()
|
||||
{
|
||||
timeTmps.Clear();
|
||||
timeTexts.Clear();
|
||||
|
||||
if (timeTmp != null) timeTmps.Add(timeTmp);
|
||||
if (timeText != null) timeTexts.Add(timeText);
|
||||
|
||||
if (timeTmps.Count == 0 && timeTexts.Count == 0)
|
||||
{
|
||||
Transform timeRoot = null;
|
||||
if (musicRoot != null)
|
||||
{
|
||||
var all = musicRoot.GetComponentsInChildren<Transform>(true);
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
var t = all[i];
|
||||
if (t == null) continue;
|
||||
if (string.Equals(t.name, timeRootName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
timeRoot = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (timeRoot == null)
|
||||
{
|
||||
var timeGo = GameObject.Find(timeRootName);
|
||||
if (timeGo != null) timeRoot = timeGo.transform;
|
||||
}
|
||||
|
||||
if (timeRoot != null)
|
||||
{
|
||||
timeTmps.AddRange(timeRoot.GetComponentsInChildren<TMP_Text>(true));
|
||||
timeTexts.AddRange(timeRoot.GetComponentsInChildren<Text>(true));
|
||||
if (!timeRoot.gameObject.activeSelf)
|
||||
timeRoot.gameObject.SetActive(true);
|
||||
for (int i = 0; i < timeTmps.Count; i++)
|
||||
{
|
||||
if (timeTmps[i] != null && !timeTmps[i].gameObject.activeSelf)
|
||||
timeTmps[i].gameObject.SetActive(true);
|
||||
}
|
||||
for (int i = 0; i < timeTexts.Count; i++)
|
||||
{
|
||||
if (timeTexts[i] != null && !timeTexts[i].gameObject.activeSelf)
|
||||
timeTexts[i].gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (timeTmps.Count == 0 && timeTexts.Count == 0)
|
||||
{
|
||||
var allTmps = Object.FindObjectsByType<TMP_Text>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
foreach (var t in allTmps)
|
||||
{
|
||||
if (t == null) continue;
|
||||
if (t.name.ToUpper().Contains("TIME") || (t.text != null && t.text.ToUpper().Contains("TIME")))
|
||||
{
|
||||
timeTmps.Add(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (timeTmps.Count == 0 && timeTexts.Count == 0)
|
||||
{
|
||||
var allTexts = Object.FindObjectsByType<Text>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
foreach (var t in allTexts)
|
||||
{
|
||||
if (t == null) continue;
|
||||
if (t.name.ToUpper().Contains("TIME") || (t.text != null && t.text.ToUpper().Contains("TIME")))
|
||||
{
|
||||
timeTexts.Add(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _buttonsBound = false;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
return;
|
||||
|
||||
if (_isGameplayScene && !_spectrumHiddenInGameplay)
|
||||
{
|
||||
HideSpectrumInGameplay(_cachedGameplaySceneName);
|
||||
_spectrumHiddenInGameplay = true;
|
||||
}
|
||||
|
||||
if (!_buttonsBound)
|
||||
{
|
||||
BindButtons();
|
||||
_buttonsBound = true;
|
||||
}
|
||||
|
||||
if (useManualMusicToggle && musicToggleButton != null && Input.GetMouseButtonDown(0))
|
||||
{
|
||||
if (IsPointerOverButton(musicToggleButton))
|
||||
ToggleMusicPic();
|
||||
}
|
||||
|
||||
// keep spectrum alive if MusicPic gets rebuilt or moved
|
||||
if (spectrumRoot == null && musicRoot != null)
|
||||
{
|
||||
EnsureSpectrum();
|
||||
}
|
||||
|
||||
var mgr = BgmPlaybackManager.Instance;
|
||||
if (mgr == null || !mgr.IsReady)
|
||||
return;
|
||||
|
||||
float total = mgr.TotalTime;
|
||||
float current = mgr.CurrentTime;
|
||||
if (total <= 0.01f) return;
|
||||
|
||||
float t = Mathf.Clamp01(current / total);
|
||||
if (progressSlider != null)
|
||||
progressSlider.value = t;
|
||||
if (progressImage != null)
|
||||
progressImage.fillAmount = t;
|
||||
|
||||
UpdatePointer(t);
|
||||
|
||||
int curS = Mathf.FloorToInt(current);
|
||||
int totS = Mathf.FloorToInt(total);
|
||||
if (curS != _lastSeconds || totS != _lastTotalSeconds)
|
||||
{
|
||||
_lastSeconds = curS;
|
||||
_lastTotalSeconds = totS;
|
||||
|
||||
_sb.Clear();
|
||||
AppendTime(_sb, curS);
|
||||
_sb.Append(" / ");
|
||||
AppendTime(_sb, totS);
|
||||
string timeStr = _sb.ToString();
|
||||
|
||||
for (int i = 0; i < timeTmps.Count; i++)
|
||||
{
|
||||
if (timeTmps[i] != null) timeTmps[i].text = timeStr;
|
||||
}
|
||||
for (int i = 0; i < timeTexts.Count; i++)
|
||||
{
|
||||
if (timeTexts[i] != null) timeTexts[i].text = timeStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendTime(System.Text.StringBuilder sb, int totalSeconds)
|
||||
{
|
||||
int m = totalSeconds / 60;
|
||||
int s = totalSeconds % 60;
|
||||
if (m < 10) sb.Append('0');
|
||||
sb.Append(m);
|
||||
sb.Append(':');
|
||||
if (s < 10) sb.Append('0');
|
||||
sb.Append(s);
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (musicRoot != null && spectrumRoot != null && enableMusicPicGyro)
|
||||
spectrumRoot.localRotation = musicRoot.localRotation;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void UpdatePointer(float t)
|
||||
{
|
||||
if (pointerRect == null || progressRect == null) return;
|
||||
var parent = pointerRect.parent as RectTransform;
|
||||
if (parent == null) return;
|
||||
|
||||
float x = Mathf.Lerp(pointerStartPos.x, pointerEndPos.x, t);
|
||||
pointerRect.anchoredPosition = new Vector2(x + pointerOffset.x, pointerStartPos.y + pointerOffset.y);
|
||||
}
|
||||
|
||||
private void CleanupProgressOutsideMusicRoot()
|
||||
{
|
||||
var all = Resources.FindObjectsOfTypeAll<RectTransform>();
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
var rt = all[i];
|
||||
if (rt == null) continue;
|
||||
if (!string.Equals(rt.name, progressName, StringComparison.OrdinalIgnoreCase)) continue;
|
||||
if (musicRoot != null && rt.transform.IsChildOf(musicRoot)) continue;
|
||||
if (Application.isPlaying)
|
||||
Destroy(rt.gameObject);
|
||||
else
|
||||
DestroyImmediate(rt.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void BindButtons()
|
||||
{
|
||||
if (prevButton == null) prevButton = FindButton(prevButtonName);
|
||||
if (nextButton == null) nextButton = FindButton(nextButtonName);
|
||||
if (pauseButton == null) pauseButton = FindButton(pauseButtonName);
|
||||
if (musicToggleButton == null) musicToggleButton = FindButton(musicToggleButtonName);
|
||||
useManualMusicToggle = musicToggleButton == null;
|
||||
|
||||
var mgr = BgmPlaybackManager.Instance ?? BgmPlaybackManager.EnsureInstance();
|
||||
if (prevButton != null)
|
||||
{
|
||||
prevButton.onClick.RemoveAllListeners();
|
||||
prevButton.onClick.AddListener(mgr.Previous);
|
||||
}
|
||||
if (nextButton != null)
|
||||
{
|
||||
nextButton.onClick.RemoveAllListeners();
|
||||
nextButton.onClick.AddListener(mgr.Next);
|
||||
}
|
||||
if (pauseButton != null)
|
||||
{
|
||||
pauseButton.onClick.RemoveAllListeners();
|
||||
pauseButton.onClick.AddListener(mgr.TogglePause);
|
||||
}
|
||||
if (musicToggleButton != null)
|
||||
{
|
||||
if (bindMusicToggleButton)
|
||||
{
|
||||
musicToggleButton.onClick.RemoveAllListeners();
|
||||
musicToggleButton.onClick.AddListener(ToggleMusicPic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Button FindButton(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) return null;
|
||||
var go = FindByNameContains(name);
|
||||
if (go == null) return null;
|
||||
return go.GetComponent<Button>();
|
||||
}
|
||||
|
||||
private bool IsPointerOverButton(Button button)
|
||||
{
|
||||
if (button == null) return false;
|
||||
RectTransform rect = button.GetComponent<RectTransform>();
|
||||
if (rect == null)
|
||||
rect = button.targetGraphic != null ? button.targetGraphic.rectTransform : null;
|
||||
if (rect == null)
|
||||
{
|
||||
var graphics = button.GetComponentsInChildren<Graphic>(true);
|
||||
rect = GetLargestRect(graphics);
|
||||
}
|
||||
if (rect == null) return false;
|
||||
|
||||
var canvas = rect.GetComponentInParent<Canvas>();
|
||||
Camera cam = (canvas != null && canvas.renderMode != RenderMode.ScreenSpaceOverlay) ? canvas.worldCamera : null;
|
||||
return RectTransformUtility.RectangleContainsScreenPoint(rect, Input.mousePosition, cam);
|
||||
}
|
||||
|
||||
private RectTransform GetLargestRect(Graphic[] graphics)
|
||||
{
|
||||
if (graphics == null || graphics.Length == 0) return null;
|
||||
RectTransform best = null;
|
||||
float bestArea = 0f;
|
||||
for (int i = 0; i < graphics.Length; i++)
|
||||
{
|
||||
var g = graphics[i];
|
||||
if (g == null) continue;
|
||||
var rt = g.rectTransform;
|
||||
float area = Mathf.Abs(rt.rect.width * rt.rect.height);
|
||||
if (area > bestArea)
|
||||
{
|
||||
bestArea = area;
|
||||
best = rt;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
private GameObject FindByNameContains(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) return null;
|
||||
var all = Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
var t = all[i];
|
||||
if (t == null) continue;
|
||||
if (!t.gameObject.scene.IsValid() || !t.gameObject.scene.isLoaded) continue;
|
||||
var n = t.name.Replace(" ", "");
|
||||
var target = name.Replace(" ", "");
|
||||
if (n.Contains(target))
|
||||
return t.gameObject;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void EnsureSpectrum()
|
||||
{
|
||||
if (musicRoot == null)
|
||||
{
|
||||
var foundMusic = FindByNameContains(musicRootName);
|
||||
if (foundMusic != null)
|
||||
musicRoot = foundMusic.GetComponent<RectTransform>();
|
||||
}
|
||||
if (musicRoot == null)
|
||||
{
|
||||
CleanupSpectrumRoots(true);
|
||||
return;
|
||||
}
|
||||
|
||||
RectTransform existing = musicRoot.Find(spectrumRootName) as RectTransform;
|
||||
var activeScene = SceneManager.GetActiveScene();
|
||||
var all = Resources.FindObjectsOfTypeAll<RectTransform>();
|
||||
List<RectTransform> found = new List<RectTransform>();
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
var rt = all[i];
|
||||
if (rt == null) continue;
|
||||
if (!rt.gameObject.scene.IsValid() || rt.gameObject.scene != activeScene) continue;
|
||||
if (!string.Equals(rt.name, spectrumRootName, StringComparison.OrdinalIgnoreCase)) continue;
|
||||
found.Add(rt);
|
||||
}
|
||||
|
||||
RectTransform preferred = null;
|
||||
for (int i = 0; i < found.Count; i++)
|
||||
{
|
||||
var rt = found[i];
|
||||
if (rt != null && rt.transform.IsChildOf(musicRoot))
|
||||
{
|
||||
preferred = rt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (preferred == null && found.Count > 0)
|
||||
preferred = found[0];
|
||||
|
||||
if (preferred != null)
|
||||
{
|
||||
if (preferred.parent != musicRoot)
|
||||
preferred.SetParent(musicRoot, false);
|
||||
existing = preferred;
|
||||
}
|
||||
|
||||
if (existing == null)
|
||||
{
|
||||
var any = FindByNameContains(spectrumRootName);
|
||||
if (any != null)
|
||||
existing = any.transform as RectTransform;
|
||||
}
|
||||
if (existing == null)
|
||||
{
|
||||
var go = new GameObject(spectrumRootName, typeof(RectTransform));
|
||||
var rt = go.GetComponent<RectTransform>();
|
||||
rt.SetParent(musicRoot, false);
|
||||
rt.sizeDelta = new Vector2(420f, 120f);
|
||||
rt.anchoredPosition = spectrumPosition;
|
||||
existing = rt;
|
||||
}
|
||||
else if (existing.parent != musicRoot)
|
||||
{
|
||||
existing.SetParent(musicRoot, false);
|
||||
}
|
||||
spectrumRoot = existing as RectTransform;
|
||||
if (spectrumRoot != null)
|
||||
{
|
||||
spectrumRoot.localRotation = Quaternion.identity;
|
||||
spectrumRoot.localScale = Vector3.one;
|
||||
spectrumRoot.anchoredPosition = spectrumPosition;
|
||||
spectrumRoot.gameObject.SetActive(true);
|
||||
}
|
||||
var viz = existing.GetComponent<BgmSpectrumVisualizer>();
|
||||
if (viz == null)
|
||||
viz = existing.gameObject.AddComponent<BgmSpectrumVisualizer>();
|
||||
if (viz != null)
|
||||
viz.enabled = true;
|
||||
CleanupSpectrumRoots(false);
|
||||
}
|
||||
|
||||
private void EnsureMusicPicCanvas()
|
||||
{
|
||||
EnsureMusicPicCanvas(null);
|
||||
}
|
||||
|
||||
private void EnsureMusicPicCanvas(Canvas sceneCanvas)
|
||||
{
|
||||
if (!keepMusicPicAcrossScenes || musicRoot == null)
|
||||
return;
|
||||
|
||||
var currentCanvas = musicRoot.GetComponentInParent<Canvas>();
|
||||
var persistent = GameObject.Find(musicPicCanvasName);
|
||||
Canvas persistentCanvas = null;
|
||||
if (persistent == null)
|
||||
{
|
||||
var go = new GameObject(musicPicCanvasName, typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster));
|
||||
persistentCanvas = go.GetComponent<Canvas>();
|
||||
persistentCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
var scaler = go.GetComponent<CanvasScaler>();
|
||||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||||
scaler.referenceResolution = new Vector2(1920f, 1080f);
|
||||
scaler.matchWidthOrHeight = 0.5f;
|
||||
DontDestroyOnLoad(go);
|
||||
persistent = go;
|
||||
}
|
||||
else
|
||||
{
|
||||
persistentCanvas = persistent.GetComponent<Canvas>();
|
||||
}
|
||||
|
||||
var sourceCanvas = sceneCanvas != null ? sceneCanvas : currentCanvas;
|
||||
if (sourceCanvas != null && persistentCanvas != null)
|
||||
{
|
||||
persistentCanvas.renderMode = sourceCanvas.renderMode;
|
||||
persistentCanvas.worldCamera = sourceCanvas.worldCamera;
|
||||
persistentCanvas.planeDistance = sourceCanvas.planeDistance;
|
||||
persistentCanvas.sortingLayerID = sourceCanvas.sortingLayerID;
|
||||
persistentCanvas.overrideSorting = true;
|
||||
persistentCanvas.sortingOrder = sourceCanvas.sortingOrder + 50;
|
||||
var srcScaler = sourceCanvas.GetComponent<CanvasScaler>();
|
||||
var dstScaler = persistentCanvas.GetComponent<CanvasScaler>();
|
||||
if (srcScaler != null && dstScaler != null)
|
||||
{
|
||||
dstScaler.uiScaleMode = srcScaler.uiScaleMode;
|
||||
dstScaler.referenceResolution = srcScaler.referenceResolution;
|
||||
dstScaler.matchWidthOrHeight = srcScaler.matchWidthOrHeight;
|
||||
dstScaler.referencePixelsPerUnit = srcScaler.referencePixelsPerUnit;
|
||||
}
|
||||
}
|
||||
|
||||
if (musicRoot != null && musicRoot.transform.parent != persistent.transform)
|
||||
musicRoot.SetParent(persistent.transform, false);
|
||||
}
|
||||
|
||||
private Canvas FindSceneCanvas()
|
||||
{
|
||||
var canvases = Object.FindObjectsByType<Canvas>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
var activeScene = SceneManager.GetActiveScene();
|
||||
for (int i = 0; i < canvases.Length; i++)
|
||||
{
|
||||
var c = canvases[i];
|
||||
if (c == null) continue;
|
||||
if (c.gameObject.scene != activeScene) continue;
|
||||
if (c.name == musicPicCanvasName) continue;
|
||||
return c;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void EnsureMusicPicCanvasGroup()
|
||||
{
|
||||
if (musicRoot == null)
|
||||
return;
|
||||
if (musicPicGroup == null)
|
||||
musicPicGroup = musicRoot.GetComponent<CanvasGroup>();
|
||||
if (musicPicGroup == null)
|
||||
musicPicGroup = musicRoot.gameObject.AddComponent<CanvasGroup>();
|
||||
musicRoot.SetAsLastSibling();
|
||||
}
|
||||
|
||||
private void ApplyDefaultMusicPicVisibility(string sceneName)
|
||||
{
|
||||
bool shouldShow = false;
|
||||
if (lobbyShowRoutine != null)
|
||||
{
|
||||
StopCoroutine(lobbyShowRoutine);
|
||||
lobbyShowRoutine = null;
|
||||
}
|
||||
|
||||
if (musicRoot != null && hasExplicitMusicRoot)
|
||||
SetMusicPicVisible(shouldShow, true);
|
||||
|
||||
if (sceneName == "gamePlay_gamePlay")
|
||||
{
|
||||
CleanupSpectrumRoots(true);
|
||||
HideSpectrumInGameplay(sceneName);
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleMusicPic()
|
||||
{
|
||||
if (musicRoot == null || !hasExplicitMusicRoot)
|
||||
Bind();
|
||||
if (musicRoot == null || !hasExplicitMusicRoot)
|
||||
{
|
||||
var go = FindByNameContains(musicRootName);
|
||||
if (go != null)
|
||||
{
|
||||
musicRoot = go.GetComponent<RectTransform>();
|
||||
hasExplicitMusicRoot = musicRoot != null;
|
||||
}
|
||||
}
|
||||
if (musicRoot == null || !hasExplicitMusicRoot) return;
|
||||
SetMusicPicVisible(!musicPicVisible, false);
|
||||
}
|
||||
|
||||
public RectTransform GetSpectrumRoot()
|
||||
{
|
||||
return spectrumRoot;
|
||||
}
|
||||
|
||||
private void SetMusicPicVisible(bool visible, bool instant)
|
||||
{
|
||||
if (musicRoot == null) return;
|
||||
EnsureMusicPicCanvasGroup();
|
||||
|
||||
if (musicPicTween != null)
|
||||
{
|
||||
StopCoroutine(musicPicTween);
|
||||
musicPicTween = null;
|
||||
}
|
||||
|
||||
musicPicVisible = visible;
|
||||
|
||||
if (instant)
|
||||
{
|
||||
if (musicPicGroup != null)
|
||||
{
|
||||
musicPicGroup.alpha = visible ? 1f : 0f;
|
||||
musicPicGroup.interactable = visible;
|
||||
musicPicGroup.blocksRaycasts = visible;
|
||||
}
|
||||
musicRoot.gameObject.SetActive(visible);
|
||||
if (!visible)
|
||||
CleanupSpectrumRoots(true);
|
||||
return;
|
||||
}
|
||||
|
||||
musicRoot.gameObject.SetActive(true);
|
||||
musicPicTween = StartCoroutine(FadeMusicPic(visible));
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator FadeMusicPic(bool visibleAtEnd)
|
||||
{
|
||||
if (musicPicGroup == null)
|
||||
yield break;
|
||||
|
||||
float start = musicPicGroup.alpha;
|
||||
float target = visibleAtEnd ? 1f : 0f;
|
||||
float t = 0f;
|
||||
while (t < 1f)
|
||||
{
|
||||
float dt = useUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime;
|
||||
t += dt / Mathf.Max(0.0001f, musicPicFadeDuration);
|
||||
float eased = Mathf.SmoothStep(0f, 1f, t);
|
||||
musicPicGroup.alpha = Mathf.LerpUnclamped(start, target, eased);
|
||||
yield return null;
|
||||
}
|
||||
musicPicGroup.alpha = target;
|
||||
musicPicGroup.interactable = visibleAtEnd;
|
||||
musicPicGroup.blocksRaycasts = visibleAtEnd;
|
||||
if (!visibleAtEnd && musicRoot != null)
|
||||
musicRoot.gameObject.SetActive(false);
|
||||
if (!visibleAtEnd)
|
||||
CleanupSpectrumRoots(true);
|
||||
}
|
||||
|
||||
private void CleanupSpectrumRoots(bool disableOnly)
|
||||
{
|
||||
var all = Resources.FindObjectsOfTypeAll<RectTransform>();
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
var rt = all[i];
|
||||
if (rt == null) continue;
|
||||
if (!string.Equals(rt.name, spectrumRootName, StringComparison.OrdinalIgnoreCase)) continue;
|
||||
if (musicRoot != null && rt.transform.IsChildOf(musicRoot)) continue;
|
||||
if (disableOnly)
|
||||
{
|
||||
rt.gameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
Destroy(rt.gameObject);
|
||||
else
|
||||
DestroyImmediate(rt.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HideSpectrumInGameplay(string sceneName)
|
||||
{
|
||||
if (sceneName != gameplaySceneName)
|
||||
return;
|
||||
|
||||
var all = Resources.FindObjectsOfTypeAll<RectTransform>();
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
var rt = all[i];
|
||||
if (rt == null) continue;
|
||||
if (!string.Equals(rt.name, spectrumRootName, StringComparison.OrdinalIgnoreCase)) continue;
|
||||
if (!rt.gameObject.scene.IsValid() || !rt.gameObject.scene.isLoaded) continue;
|
||||
var viz = rt.GetComponent<BgmSpectrumVisualizer>();
|
||||
if (viz != null) viz.enabled = false;
|
||||
rt.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (spectrumRoot != null)
|
||||
{
|
||||
var viz = spectrumRoot.GetComponent<BgmSpectrumVisualizer>();
|
||||
if (viz != null) viz.enabled = false;
|
||||
spectrumRoot.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator ShowLobbyMusicPicNextFrame()
|
||||
{
|
||||
int tries = 0;
|
||||
while (tries < 3)
|
||||
{
|
||||
yield return null;
|
||||
if (musicRoot == null || !hasExplicitMusicRoot)
|
||||
Bind();
|
||||
|
||||
if (musicRoot != null && hasExplicitMusicRoot)
|
||||
break;
|
||||
|
||||
tries++;
|
||||
}
|
||||
|
||||
if (musicRoot == null || !hasExplicitMusicRoot)
|
||||
yield break;
|
||||
|
||||
EnsureSpectrum();
|
||||
EnsureMusicPicCanvasGroup();
|
||||
if (musicPicGroup != null)
|
||||
musicPicGroup.alpha = 0f;
|
||||
SetMusicPicVisible(true, false);
|
||||
}
|
||||
|
||||
private List<RectTransform> FindAllMusicPic()
|
||||
{
|
||||
var list = new List<RectTransform>();
|
||||
var all = Resources.FindObjectsOfTypeAll<RectTransform>();
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
var rt = all[i];
|
||||
if (rt == null) continue;
|
||||
if (!rt.gameObject.scene.IsValid() || !rt.gameObject.scene.isLoaded) continue;
|
||||
var n = rt.name.Replace(" ", "");
|
||||
var target = musicRootName.Replace(" ", "");
|
||||
if (n.IndexOf("Canvas", StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
continue;
|
||||
|
||||
bool match = n.Equals(target, StringComparison.OrdinalIgnoreCase) ||
|
||||
n.StartsWith(target + "(", StringComparison.OrdinalIgnoreCase) ||
|
||||
n.StartsWith(target + "_", StringComparison.OrdinalIgnoreCase);
|
||||
if (match)
|
||||
list.Add(rt);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user