Files
BeatSaber/Assets/Script/SongSelectManager.cs
T

204 lines
7.0 KiB
C#
Raw Normal View History

using System.Collections.Generic;
using System.IO;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class SongSelectManager : MonoBehaviour
{
[SerializeField] private Button tabAllBtn;
[SerializeField] private Button tabOwnedBtn;
[SerializeField] private RectTransform cardContainer;
[SerializeField] private SongDetailPanel detailPanel;
[SerializeField] private DownloadManager downloadManager;
[SerializeField] private GameObject loadingOverlay;
[SerializeField] private GameObject errorOverlay;
[SerializeField] private TMP_Text errorText;
[SerializeField] private TMP_FontAsset cardFont;
private static readonly Color TabActive = Color.white;
private static readonly Color TabInactive = new Color(0.6f, 0.6f, 0.6f);
private static string CachePath =>
Path.Combine(Application.persistentDataPath, "songs_cache.json");
private List<SongInfo> allSongs = new List<SongInfo>();
private bool showingOwned = false;
private void Start()
{
tabAllBtn .onClick.AddListener(() => SwitchTab(false));
tabOwnedBtn.onClick.AddListener(() => SwitchTab(true));
detailPanel.gameObject.SetActive(false);
SetTabVisual(false);
FetchSongs();
}
private void SwitchTab(bool owned)
{
showingOwned = owned;
SetTabVisual(owned);
RefreshCards();
}
private void SetTabVisual(bool owned)
{
ApplyTabColor(tabAllBtn, owned ? TabInactive : TabActive);
ApplyTabColor(tabOwnedBtn, owned ? TabActive : TabInactive);
}
private static void ApplyTabColor(Button btn, Color c)
{
var colors = btn.colors;
colors.normalColor = c;
btn.colors = colors;
}
private void FetchSongs()
{
loadingOverlay.SetActive(true);
errorOverlay .SetActive(false);
downloadManager.FetchSongsList(
onSuccess: list =>
{
allSongs = list.songs;
SaveCache(list);
SongLibrary.Instance.ValidateWithFileSystem(downloadManager, list.songs);
loadingOverlay.SetActive(false);
RefreshCards();
},
onError: _ =>
{
SongsList cached = LoadCache();
loadingOverlay.SetActive(false);
if (cached != null)
{
allSongs = cached.songs;
RefreshCards();
}
else
{
errorOverlay.SetActive(true);
errorText.text = "Failed to connect to server\nPlease check your internet connection";
}
});
}
public void RefreshCards()
{
for (int i = cardContainer.childCount - 1; i >= 0; i--)
Destroy(cardContainer.GetChild(i).gameObject);
List<SongInfo> songs = showingOwned
? allSongs.FindAll(s => SongLibrary.Instance.IsSongDownloaded(s.id))
: allSongs;
foreach (SongInfo song in songs)
SpawnCard(song);
}
private void SpawnCard(SongInfo song)
{
bool downloaded = SongLibrary.Instance.IsSongDownloaded(song.id);
var card = new GameObject(song.title);
card.transform.SetParent(cardContainer, false);
var le = card.AddComponent<LayoutElement>();
le.preferredHeight = 13f;
le.flexibleWidth = 1f;
var bg = card.AddComponent<Image>();
bg.color = new Color(1f, 1f, 1f, 0.06f);
var btn = card.AddComponent<Button>();
btn.targetGraphic = bg;
var bc = btn.colors;
bc.normalColor = new Color(1f, 1f, 1f, 0.06f);
bc.highlightedColor = new Color(0.4f, 0.75f, 1f, 0.25f);
bc.pressedColor = new Color(0.3f, 0.60f, 0.9f, 0.45f);
bc.fadeDuration = 0.1f;
btn.colors = bc;
// Title
var titleGO = new GameObject("Title");
titleGO.transform.SetParent(card.transform, false);
var tr = titleGO.AddComponent<RectTransform>();
tr.anchorMin = new Vector2(0f, 0.5f);
tr.anchorMax = new Vector2(1f, 1f);
tr.offsetMin = new Vector2(5f, 0f);
tr.offsetMax = new Vector2(downloaded ? -18f : -3f, -1f);
var tTmp = titleGO.AddComponent<TextMeshProUGUI>();
if (cardFont != null) tTmp.font = cardFont;
tTmp.text = song.title;
tTmp.fontSize = 5f;
tTmp.color = Color.white;
tTmp.alignment = TextAlignmentOptions.MidlineLeft;
tTmp.overflowMode = TextOverflowModes.Ellipsis;
// Artist
var artistGO = new GameObject("Artist");
artistGO.transform.SetParent(card.transform, false);
var ar = artistGO.AddComponent<RectTransform>();
ar.anchorMin = new Vector2(0f, 0f);
ar.anchorMax = new Vector2(1f, 0.5f);
ar.offsetMin = new Vector2(5f, 1f);
ar.offsetMax = new Vector2(-3f, 0f);
var aTmp = artistGO.AddComponent<TextMeshProUGUI>();
if (cardFont != null) aTmp.font = cardFont;
aTmp.text = song.artist;
aTmp.fontSize = 4f;
aTmp.color = new Color(1f, 1f, 1f, 0.6f);
aTmp.alignment = TextAlignmentOptions.MidlineLeft;
// Downloaded badge
if (downloaded)
{
var badge = new GameObject("Badge");
badge.transform.SetParent(card.transform, false);
var br = badge.AddComponent<RectTransform>();
br.anchorMin = new Vector2(1f, 0.5f);
br.anchorMax = new Vector2(1f, 0.5f);
br.pivot = new Vector2(1f, 0.5f);
br.anchoredPosition = new Vector2(-3f, 0f);
br.sizeDelta = new Vector2(14f, 5.5f);
badge.AddComponent<Image>().color = new Color(0.2f, 0.78f, 0.4f, 0.85f);
var bl = new GameObject("Text");
bl.transform.SetParent(badge.transform, false);
var blr = bl.AddComponent<RectTransform>();
blr.anchorMin = Vector2.zero;
blr.anchorMax = Vector2.one;
blr.offsetMin = blr.offsetMax = Vector2.zero;
var blTmp = bl.AddComponent<TextMeshProUGUI>();
blTmp.text = "OWNED";
blTmp.fontSize = 3.5f;
blTmp.color = Color.white;
blTmp.alignment = TextAlignmentOptions.Center;
}
SongInfo captured = song;
btn.onClick.AddListener(() => OnCardClicked(captured));
}
private void OnCardClicked(SongInfo song)
{
detailPanel.gameObject.SetActive(true);
detailPanel.Show(song, downloadManager, this);
}
private static void SaveCache(SongsList list)
{
try { File.WriteAllText(CachePath, JsonUtility.ToJson(list, true)); }
catch { }
}
private static SongsList LoadCache()
{
if (!File.Exists(CachePath)) return null;
try { return JsonUtility.FromJson<SongsList>(File.ReadAllText(CachePath)); }
catch { return null; }
}
}