695 lines
23 KiB
C#
695 lines
23 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using DG.Tweening;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.SceneManagement;
|
|
using UnityEngine.UI;
|
|
using Bansonic;
|
|
|
|
public class UI_SongsSelect_RuntimeFeatures : MonoBehaviour
|
|
{
|
|
[Header("Scene")]
|
|
[SerializeField] private string requiredSceneName = "Songs_Select";
|
|
[SerializeField] private string gameplaySceneName = "gamePlay_gamePlay";
|
|
|
|
[Header("Targets")]
|
|
[SerializeField] private string enterButtonName = "bottom";
|
|
[SerializeField] private string enterButtonParentName = "enterBar";
|
|
[SerializeField] private string autoPlayToggleName = "enableAutoPlayToggle";
|
|
[SerializeField] private string difficultiesRootName = "horizontalDifficultiesLayouts";
|
|
|
|
[Header("Difficulty Indicator Pop")]
|
|
[SerializeField] private float diffPopScaleFrom = 1.25f;
|
|
[SerializeField] private float diffPopTime = 0.26f;
|
|
[SerializeField] private float diffPopFadeInTime = 0.08f;
|
|
[SerializeField] private Ease diffPopEase = Ease.OutBack;
|
|
|
|
[Header("Difficulty ID Roll")]
|
|
[SerializeField] private string difficultyIdName = "difficultyID";
|
|
[SerializeField] private string difficultyIdGroundName = "difficultyIDGround";
|
|
[SerializeField] private float difficultyIdStepDelayFast = 0.03f;
|
|
[SerializeField] private float difficultyIdStepDelaySlow = 0.11f;
|
|
[SerializeField] private bool difficultyIdUseUnscaledTime = true;
|
|
|
|
private Button enterButton;
|
|
private UnityAction enterAction;
|
|
private Toggle autoPlayToggle;
|
|
private UnityAction<bool> autoPlayToggleAction;
|
|
private Coroutine bindRoutine;
|
|
private Coroutine bgmKeepAliveRoutine;
|
|
private Coroutine difficultyIdRollCoroutine;
|
|
private readonly Dictionary<Button, UnityAction> diffActions = new Dictionary<Button, UnityAction>();
|
|
private readonly Dictionary<Toggle, UnityAction<bool>> diffToggleActions = new Dictionary<Toggle, UnityAction<bool>>();
|
|
private readonly List<Text> difficultyIdDisplayTexts = new List<Text>();
|
|
private int difficultyIdDisplayed = int.MinValue;
|
|
private float nextDifficultyIdRefreshTime = 0f;
|
|
|
|
private void OnEnable()
|
|
{
|
|
var bgm = BgmPlaybackManager.Instance ?? BgmPlaybackManager.EnsureInstance();
|
|
if (bgm != null)
|
|
{
|
|
bgm.autoPlay = true;
|
|
if (bgm.audioSource != null)
|
|
{
|
|
bgm.audioSource.mute = false;
|
|
if (bgm.audioSource.volume <= 0.001f)
|
|
bgm.audioSource.volume = 1f;
|
|
}
|
|
bgm.EnsurePlaying();
|
|
}
|
|
|
|
if (bindRoutine != null)
|
|
{
|
|
StopCoroutine(bindRoutine);
|
|
bindRoutine = null;
|
|
}
|
|
|
|
if (bgmKeepAliveRoutine != null)
|
|
StopCoroutine(bgmKeepAliveRoutine);
|
|
bgmKeepAliveRoutine = StartCoroutine(EnsureBgmAliveRoutine());
|
|
|
|
RebindSoon();
|
|
ResolveDifficultyIdDisplayTexts();
|
|
RefreshDifficultyIdDisplay(forceInstant: true);
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (bindRoutine != null)
|
|
{
|
|
StopCoroutine(bindRoutine);
|
|
bindRoutine = null;
|
|
}
|
|
if (bgmKeepAliveRoutine != null)
|
|
{
|
|
StopCoroutine(bgmKeepAliveRoutine);
|
|
bgmKeepAliveRoutine = null;
|
|
}
|
|
if (difficultyIdRollCoroutine != null)
|
|
{
|
|
StopCoroutine(difficultyIdRollCoroutine);
|
|
difficultyIdRollCoroutine = null;
|
|
}
|
|
Unbind();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!IsInRequiredScene())
|
|
return;
|
|
|
|
if (Time.unscaledTime < nextDifficultyIdRefreshTime)
|
|
return;
|
|
|
|
nextDifficultyIdRefreshTime = Time.unscaledTime + 0.06f;
|
|
RefreshDifficultyIdDisplay(forceInstant: false);
|
|
}
|
|
|
|
private IEnumerator EnsureBgmAliveRoutine()
|
|
{
|
|
while (enabled)
|
|
{
|
|
if (IsInRequiredScene())
|
|
{
|
|
var bgm = BgmPlaybackManager.Instance ?? BgmPlaybackManager.EnsureInstance();
|
|
if (bgm != null)
|
|
{
|
|
bgm.autoPlay = true;
|
|
if (bgm.audioSource != null)
|
|
{
|
|
bgm.audioSource.mute = false;
|
|
if (bgm.audioSource.volume <= 0.001f)
|
|
bgm.audioSource.volume = 1f;
|
|
}
|
|
bgm.EnsurePlaying();
|
|
}
|
|
}
|
|
yield return new WaitForSecondsRealtime(0.25f);
|
|
}
|
|
bgmKeepAliveRoutine = null;
|
|
}
|
|
|
|
public void RebindSoon()
|
|
{
|
|
if (bindRoutine != null)
|
|
StopCoroutine(bindRoutine);
|
|
bindRoutine = StartCoroutine(BindRoutine());
|
|
}
|
|
|
|
private IEnumerator BindRoutine()
|
|
{
|
|
// Wait a few frames so scene-internal scripts finish wiring first.
|
|
yield return null;
|
|
TryBindAll();
|
|
yield return null;
|
|
TryBindAll();
|
|
yield return null;
|
|
TryBindAll();
|
|
bindRoutine = null;
|
|
}
|
|
|
|
private void TryBindAll()
|
|
{
|
|
if (!IsInRequiredScene())
|
|
return;
|
|
|
|
DisableDecorativeDifficultyRaycasts();
|
|
ResolveDifficultyIdDisplayTexts();
|
|
BindEnterButton();
|
|
BindAutoPlayToggle();
|
|
BindDifficultyButtons();
|
|
RefreshDifficultyIdDisplay(forceInstant: false);
|
|
}
|
|
|
|
private bool IsInRequiredScene()
|
|
{
|
|
Scene scene = gameObject.scene;
|
|
if (!scene.IsValid() || !scene.isLoaded)
|
|
scene = SceneManager.GetActiveScene();
|
|
|
|
return string.IsNullOrEmpty(requiredSceneName) || scene.name == requiredSceneName;
|
|
}
|
|
|
|
private void BindEnterButton()
|
|
{
|
|
Button next = FindEnterButton();
|
|
if (next == null)
|
|
return;
|
|
|
|
if (enterButton != null && enterAction != null && enterButton != next)
|
|
enterButton.onClick.RemoveListener(enterAction);
|
|
|
|
enterButton = next;
|
|
if (enterAction == null)
|
|
enterAction = OnEnterGameplayClicked;
|
|
enterButton.onClick.RemoveListener(enterAction);
|
|
enterButton.onClick.AddListener(enterAction);
|
|
}
|
|
|
|
private void BindAutoPlayToggle()
|
|
{
|
|
Transform tr = FindInCurrentSceneByName(autoPlayToggleName);
|
|
if (tr == null)
|
|
return;
|
|
|
|
Toggle toggle = tr.GetComponent<Toggle>();
|
|
if (toggle == null)
|
|
return;
|
|
|
|
if (autoPlayToggle != null && autoPlayToggleAction != null && autoPlayToggle != toggle)
|
|
autoPlayToggle.onValueChanged.RemoveListener(autoPlayToggleAction);
|
|
|
|
autoPlayToggle = toggle;
|
|
if (autoPlayToggleAction == null)
|
|
autoPlayToggleAction = OnAutoPlayToggleChanged;
|
|
|
|
autoPlayToggle.onValueChanged.RemoveListener(autoPlayToggleAction);
|
|
autoPlayToggle.onValueChanged.AddListener(autoPlayToggleAction);
|
|
autoPlayToggle.SetIsOnWithoutNotify(GameConfig.autoPlayEnabled);
|
|
EnsureSelectableClickable(autoPlayToggle);
|
|
}
|
|
|
|
private void OnAutoPlayToggleChanged(bool isOn)
|
|
{
|
|
GameConfig.SetAutoPlayEnabled(isOn);
|
|
}
|
|
|
|
private void BindDifficultyButtons()
|
|
{
|
|
foreach (var kv in diffActions)
|
|
{
|
|
if (kv.Key != null && kv.Value != null)
|
|
kv.Key.onClick.RemoveListener(kv.Value);
|
|
}
|
|
diffActions.Clear();
|
|
foreach (var kv in diffToggleActions)
|
|
{
|
|
if (kv.Key != null && kv.Value != null)
|
|
kv.Key.onValueChanged.RemoveListener(kv.Value);
|
|
}
|
|
diffToggleActions.Clear();
|
|
|
|
Transform root = FindInCurrentSceneByName(difficultiesRootName);
|
|
if (root == null)
|
|
return;
|
|
EnsureAncestorCanvasGroupsAllowInput(root);
|
|
|
|
Button[] buttons = root.GetComponentsInChildren<Button>(true);
|
|
for (int i = 0; i < buttons.Length; i++)
|
|
{
|
|
Button btn = buttons[i];
|
|
if (btn == null)
|
|
continue;
|
|
EnsureSelectableClickable(btn);
|
|
|
|
UnityAction action = () => StartCoroutine(PlayDifficultyPopDeferred(btn.transform));
|
|
btn.onClick.RemoveListener(action);
|
|
btn.onClick.AddListener(action);
|
|
diffActions[btn] = action;
|
|
}
|
|
|
|
Toggle[] toggles = root.GetComponentsInChildren<Toggle>(true);
|
|
for (int i = 0; i < toggles.Length; i++)
|
|
{
|
|
Toggle tg = toggles[i];
|
|
if (tg == null)
|
|
continue;
|
|
EnsureSelectableClickable(tg);
|
|
|
|
UnityAction<bool> action = isOn =>
|
|
{
|
|
if (isOn)
|
|
StartCoroutine(PlayDifficultyPopDeferred(tg.transform));
|
|
};
|
|
tg.onValueChanged.RemoveListener(action);
|
|
tg.onValueChanged.AddListener(action);
|
|
diffToggleActions[tg] = action;
|
|
}
|
|
|
|
// Explicitly unlock known difficulty buttons that users reported as unclickable.
|
|
ForceEnableNamedSelectable(root, "HD");
|
|
ForceEnableNamedSelectable(root, "IN");
|
|
}
|
|
|
|
private IEnumerator PlayDifficultyPopDeferred(Transform buttonRoot)
|
|
{
|
|
yield return null;
|
|
if (buttonRoot == null)
|
|
yield break;
|
|
|
|
RectTransform target = FindDifficultyIndicator(buttonRoot);
|
|
if (target == null)
|
|
yield break;
|
|
|
|
Vector3 baseScale = target.localScale;
|
|
CanvasGroup group = target.GetComponent<CanvasGroup>();
|
|
if (group == null)
|
|
group = target.gameObject.AddComponent<CanvasGroup>();
|
|
|
|
target.DOKill();
|
|
group.DOKill();
|
|
|
|
float baseAlpha = group.alpha > 0f ? group.alpha : 1f;
|
|
target.localScale = baseScale * Mathf.Max(1.01f, diffPopScaleFrom);
|
|
group.alpha = 0f;
|
|
|
|
Sequence seq = DOTween.Sequence().SetUpdate(true);
|
|
seq.Append(group.DOFade(baseAlpha, Mathf.Max(0.01f, diffPopFadeInTime)));
|
|
seq.Join(target.DOScale(baseScale, Mathf.Max(0.01f, diffPopTime)).SetEase(diffPopEase));
|
|
}
|
|
|
|
private RectTransform FindDifficultyIndicator(Transform buttonRoot)
|
|
{
|
|
if (buttonRoot == null)
|
|
return null;
|
|
|
|
Transform candidate =
|
|
FindChildByName(buttonRoot, "selected_bottom") ??
|
|
FindChildByName(buttonRoot, "selected") ??
|
|
FindChildByName(buttonRoot, "indicator") ??
|
|
FindChildByName(buttonRoot, "mark") ??
|
|
FindChildByName(buttonRoot, "bottom");
|
|
|
|
RectTransform rt = candidate as RectTransform;
|
|
if (rt == null)
|
|
rt = buttonRoot as RectTransform;
|
|
return rt;
|
|
}
|
|
|
|
private void OnEnterGameplayClicked()
|
|
{
|
|
SongData song = ResolveSelectedSong();
|
|
if (song == null)
|
|
{
|
|
Debug.LogWarning("[Songs_Select] Enter gameplay cancelled: no selected song.");
|
|
return;
|
|
}
|
|
|
|
int difficulty = Mathf.Clamp(song.thisLevel_selectedDifficultyID, 0, 3);
|
|
TextAsset chart = song.GetChartFile(difficulty);
|
|
if (chart == null || string.IsNullOrEmpty(chart.text))
|
|
{
|
|
gNotice.error.display("未找到此难度的关卡");
|
|
Debug.LogError($"[Songs_Select] Enter gameplay cancelled: chart missing for '{song.songName}' difficulty {difficulty}.");
|
|
return;
|
|
}
|
|
|
|
SongDataHolder.SelectedSongData = song;
|
|
BeatmapManager.SetPendingSong(song, difficulty);
|
|
|
|
Time.timeScale = 1f;
|
|
SceneManager.LoadScene(gameplaySceneName, LoadSceneMode.Single);
|
|
}
|
|
|
|
private SongData ResolveSelectedSong()
|
|
{
|
|
if (SongDataHolder.SelectedSongData != null)
|
|
return SongDataHolder.SelectedSongData;
|
|
|
|
SongButton[] buttons = UnityEngine.Object.FindObjectsByType<SongButton>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
|
for (int i = 0; i < buttons.Length; i++)
|
|
{
|
|
SongButton sb = buttons[i];
|
|
if (sb == null || sb.gameObject.scene != gameObject.scene)
|
|
continue;
|
|
|
|
if (sb.selected_boarder != null && sb.selected_boarder.color.a > 0.5f)
|
|
{
|
|
SongData selected = sb.thisSong_so as SongData;
|
|
if (selected != null)
|
|
return selected;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private Button FindEnterButton()
|
|
{
|
|
Scene scene = gameObject.scene;
|
|
Transform[] all = UnityEngine.Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
|
for (int i = 0; i < all.Length; i++)
|
|
{
|
|
Transform t = all[i];
|
|
if (t == null || t.gameObject.scene != scene)
|
|
continue;
|
|
if (!string.Equals(t.name, enterButtonName, System.StringComparison.OrdinalIgnoreCase))
|
|
continue;
|
|
if (!HasAncestorNamed(t, enterButtonParentName))
|
|
continue;
|
|
|
|
Button btn = t.GetComponent<Button>();
|
|
if (btn != null)
|
|
return btn;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private bool HasAncestorNamed(Transform tr, string name)
|
|
{
|
|
Transform p = tr != null ? tr.parent : null;
|
|
while (p != null)
|
|
{
|
|
if (string.Equals(p.name, name, System.StringComparison.OrdinalIgnoreCase))
|
|
return true;
|
|
p = p.parent;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private Transform FindInCurrentSceneByName(string objectName)
|
|
{
|
|
if (string.IsNullOrEmpty(objectName))
|
|
return null;
|
|
|
|
Scene scene = gameObject.scene;
|
|
Transform[] all = UnityEngine.Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
|
for (int i = 0; i < all.Length; i++)
|
|
{
|
|
Transform t = all[i];
|
|
if (t == null || t.gameObject.scene != scene)
|
|
continue;
|
|
if (string.Equals(t.name, objectName, System.StringComparison.OrdinalIgnoreCase))
|
|
return t;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private Transform FindChildByName(Transform root, string name)
|
|
{
|
|
if (root == null || string.IsNullOrEmpty(name))
|
|
return null;
|
|
|
|
Transform[] children = root.GetComponentsInChildren<Transform>(true);
|
|
for (int i = 0; i < children.Length; i++)
|
|
{
|
|
Transform child = children[i];
|
|
if (child != null && string.Equals(child.name, name, System.StringComparison.OrdinalIgnoreCase))
|
|
return child;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private void EnsureSelectableClickable(Selectable selectable)
|
|
{
|
|
if (selectable == null) return;
|
|
selectable.interactable = true;
|
|
|
|
if (selectable.targetGraphic != null)
|
|
selectable.targetGraphic.raycastTarget = true;
|
|
|
|
EnsureAncestorCanvasGroupsAllowInput(selectable.transform);
|
|
}
|
|
|
|
private void EnsureAncestorCanvasGroupsAllowInput(Transform leaf)
|
|
{
|
|
Transform t = leaf;
|
|
int safety = 0;
|
|
while (t != null && safety++ < 16)
|
|
{
|
|
CanvasGroup cg = t.GetComponent<CanvasGroup>();
|
|
if (cg != null && cg.alpha > 0.001f)
|
|
{
|
|
cg.interactable = true;
|
|
cg.blocksRaycasts = true;
|
|
}
|
|
t = t.parent;
|
|
}
|
|
}
|
|
|
|
private void ForceEnableNamedSelectable(Transform root, string objectName)
|
|
{
|
|
if (root == null || string.IsNullOrEmpty(objectName)) return;
|
|
Transform target = FindChildByName(root, objectName);
|
|
if (target == null) return;
|
|
|
|
Button btn = target.GetComponent<Button>();
|
|
if (btn != null) EnsureSelectableClickable(btn);
|
|
|
|
Toggle tg = target.GetComponent<Toggle>();
|
|
if (tg != null) EnsureSelectableClickable(tg);
|
|
}
|
|
|
|
private void DisableDecorativeDifficultyRaycasts()
|
|
{
|
|
Scene scene = gameObject.scene;
|
|
Text[] allTexts = UnityEngine.Object.FindObjectsByType<Text>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
|
for (int i = 0; i < allTexts.Length; i++)
|
|
{
|
|
Text txt = allTexts[i];
|
|
if (txt == null || txt.gameObject.scene != scene) continue;
|
|
string n = txt.name;
|
|
if (!string.Equals(n, "difficultyID", System.StringComparison.OrdinalIgnoreCase) &&
|
|
!string.Equals(n, "difficultyIDGround", System.StringComparison.OrdinalIgnoreCase))
|
|
continue;
|
|
txt.raycastTarget = false;
|
|
}
|
|
}
|
|
|
|
private void ResolveDifficultyIdDisplayTexts()
|
|
{
|
|
difficultyIdDisplayTexts.Clear();
|
|
|
|
Scene scene = gameObject.scene;
|
|
Text[] allTexts = UnityEngine.Object.FindObjectsByType<Text>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
|
for (int i = 0; i < allTexts.Length; i++)
|
|
{
|
|
Text txt = allTexts[i];
|
|
if (txt == null || txt.gameObject.scene != scene)
|
|
continue;
|
|
|
|
string n = txt.name;
|
|
if (!string.Equals(n, difficultyIdName, System.StringComparison.OrdinalIgnoreCase) &&
|
|
!string.Equals(n, difficultyIdGroundName, System.StringComparison.OrdinalIgnoreCase))
|
|
continue;
|
|
|
|
txt.raycastTarget = false;
|
|
difficultyIdDisplayTexts.Add(txt);
|
|
}
|
|
}
|
|
|
|
private void RefreshDifficultyIdDisplay(bool forceInstant)
|
|
{
|
|
int target = GetCurrentDifficultyDisplayValue();
|
|
|
|
if (difficultyIdDisplayTexts.Count == 0)
|
|
ResolveDifficultyIdDisplayTexts();
|
|
if (difficultyIdDisplayTexts.Count == 0)
|
|
return;
|
|
|
|
if (forceInstant || difficultyIdDisplayed == int.MinValue)
|
|
{
|
|
difficultyIdDisplayed = target;
|
|
ApplyDifficultyIdDisplayValue(target);
|
|
return;
|
|
}
|
|
|
|
if (target == difficultyIdDisplayed)
|
|
{
|
|
ApplyDifficultyIdDisplayValue(target);
|
|
return;
|
|
}
|
|
|
|
if (difficultyIdRollCoroutine != null)
|
|
{
|
|
StopCoroutine(difficultyIdRollCoroutine);
|
|
difficultyIdRollCoroutine = null;
|
|
}
|
|
|
|
difficultyIdRollCoroutine = StartCoroutine(RollDifficultyIdDisplay(difficultyIdDisplayed, target));
|
|
}
|
|
|
|
private int GetCurrentDifficultyDisplayValue()
|
|
{
|
|
SongData song = ResolveSelectedSong();
|
|
if (song == null)
|
|
return 0;
|
|
|
|
int difficulty = Mathf.Clamp(song.thisLevel_selectedDifficultyID, 0, 3);
|
|
float level = GetDifficultyLevel(song, difficulty);
|
|
int rounded = Mathf.RoundToInt(level);
|
|
return Mathf.Max(0, rounded);
|
|
}
|
|
|
|
private float GetDifficultyLevel(SongData song, int difficultyId)
|
|
{
|
|
if (song == null)
|
|
return 0f;
|
|
|
|
if (song.chartFiles != null)
|
|
{
|
|
for (int i = 0; i < song.chartFiles.Count; i++)
|
|
{
|
|
ChartFileEntry entry = song.chartFiles[i];
|
|
if (entry == null || entry.difficulty != difficultyId)
|
|
continue;
|
|
return entry.difficultyLEVEL;
|
|
}
|
|
}
|
|
|
|
if (song.difficultyNumberMap != null && song.difficultyNumberMap.ContainsKey(difficultyId))
|
|
return song.difficultyNumberMap[difficultyId];
|
|
|
|
return 0f;
|
|
}
|
|
|
|
private void ApplyDifficultyIdDisplayValue(int value)
|
|
{
|
|
string text = value.ToString();
|
|
for (int i = 0; i < difficultyIdDisplayTexts.Count; i++)
|
|
{
|
|
Text t = difficultyIdDisplayTexts[i];
|
|
if (t == null)
|
|
continue;
|
|
|
|
t.text = text;
|
|
t.raycastTarget = false;
|
|
}
|
|
}
|
|
|
|
private IEnumerator RollDifficultyIdDisplay(int from, int target)
|
|
{
|
|
int distance = Mathf.Abs(target - from);
|
|
if (distance <= 0)
|
|
{
|
|
difficultyIdDisplayed = target;
|
|
ApplyDifficultyIdDisplayValue(target);
|
|
difficultyIdRollCoroutine = null;
|
|
yield break;
|
|
}
|
|
|
|
int dir = target > from ? 1 : -1;
|
|
int current = from;
|
|
for (int i = 1; i <= distance; i++)
|
|
{
|
|
current += dir;
|
|
difficultyIdDisplayed = current;
|
|
ApplyDifficultyIdDisplayValue(current);
|
|
|
|
float progress = distance <= 1 ? 1f : (float)i / distance;
|
|
float eased = progress * progress; // fast first, then slow
|
|
float delay = Mathf.Lerp(difficultyIdStepDelayFast, difficultyIdStepDelaySlow, eased);
|
|
if (difficultyIdUseUnscaledTime)
|
|
yield return new WaitForSecondsRealtime(Mathf.Max(0.005f, delay));
|
|
else
|
|
yield return new WaitForSeconds(Mathf.Max(0.005f, delay));
|
|
}
|
|
|
|
difficultyIdDisplayed = target;
|
|
ApplyDifficultyIdDisplayValue(target);
|
|
difficultyIdRollCoroutine = null;
|
|
}
|
|
|
|
private void Unbind()
|
|
{
|
|
if (enterButton != null && enterAction != null)
|
|
enterButton.onClick.RemoveListener(enterAction);
|
|
if (autoPlayToggle != null && autoPlayToggleAction != null)
|
|
autoPlayToggle.onValueChanged.RemoveListener(autoPlayToggleAction);
|
|
|
|
foreach (var kv in diffActions)
|
|
{
|
|
if (kv.Key != null && kv.Value != null)
|
|
kv.Key.onClick.RemoveListener(kv.Value);
|
|
}
|
|
diffActions.Clear();
|
|
foreach (var kv in diffToggleActions)
|
|
{
|
|
if (kv.Key != null && kv.Value != null)
|
|
kv.Key.onValueChanged.RemoveListener(kv.Value);
|
|
}
|
|
diffToggleActions.Clear();
|
|
}
|
|
}
|
|
|
|
static class UI_SongsSelect_RuntimeFeaturesBootstrap
|
|
{
|
|
private const string SceneName = "Songs_Select";
|
|
private const string HostName = "__SongsSelectRuntimeFeaturesHost";
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
|
private static void Init()
|
|
{
|
|
SceneManager.sceneLoaded -= OnSceneLoaded;
|
|
SceneManager.sceneLoaded += OnSceneLoaded;
|
|
}
|
|
|
|
private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
|
{
|
|
if (scene.name != SceneName)
|
|
return;
|
|
|
|
GameObject host = FindHostInScene(scene, HostName);
|
|
if (host == null)
|
|
{
|
|
host = new GameObject(HostName);
|
|
SceneManager.MoveGameObjectToScene(host, scene);
|
|
}
|
|
|
|
UI_SongsSelect_RuntimeFeatures features = host.GetComponent<UI_SongsSelect_RuntimeFeatures>();
|
|
if (features == null)
|
|
features = host.AddComponent<UI_SongsSelect_RuntimeFeatures>();
|
|
|
|
features.RebindSoon();
|
|
}
|
|
|
|
private static GameObject FindHostInScene(Scene scene, string hostName)
|
|
{
|
|
if (!scene.IsValid() || !scene.isLoaded)
|
|
return null;
|
|
|
|
Transform[] all = UnityEngine.Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
|
for (int i = 0; i < all.Length; i++)
|
|
{
|
|
Transform t = all[i];
|
|
if (t == null || t.gameObject.scene != scene)
|
|
continue;
|
|
if (t.name == hostName)
|
|
return t.gameObject;
|
|
}
|
|
return null;
|
|
}
|
|
}
|