static void Prefix(ref LevelPackLevelsTableView __instance, int row, ref HMUI.TableView ____tableView, ref bool ____showLevelPackHeader, ref IBeatmapLevelPack ____pack) { if (!SongLoader.AreSongsLoaded) { return; } if (____pack.beatmapLevelCollection.beatmapLevels.Length == 0) { return; } int num = ____showLevelPackHeader ? (row - 1) : row; num = Mathf.Clamp(num, 0, ____pack.beatmapLevelCollection.beatmapLevels.Length - 1); // Console.WriteLine($"Num: {num} Size: {____pack.beatmapLevelCollection.beatmapLevels.Length}"); if (!(____pack.beatmapLevelCollection.beatmapLevels[num] is OverrideClasses.CustomLevel)) { return; } OverrideClasses.CustomLevel customLevel = ____pack.beatmapLevelCollection.beatmapLevels[num] as OverrideClasses.CustomLevel; if (!customLevel) { return; } if (customLevel.coverImage == SongLoader.CustomSongsIcon) { SongLoader.LoadSprite(customLevel.customSongInfo.path + "/" + customLevel.customSongInfo.coverImagePath, customLevel); } }
public static void RefreshTable(this HMUI.TableView tableView, bool callbackTable = true) { HashSet <int> rows = new HashSet <int>(tableView.GetPrivateField <HashSet <int> >("_selectedRows")); float scrollPosition = tableView.GetPrivateField <ScrollRect>("_scrollRect").verticalNormalizedPosition; tableView.ReloadData(); tableView.GetPrivateField <ScrollRect>("_scrollRect").verticalNormalizedPosition = scrollPosition; tableView.SetPrivateField("_targetVerticalNormalizedPosition", scrollPosition); if (rows.Count > 0) { tableView.SelectRow(rows.First(), callbackTable); } }
//////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// /// <summary> /// When a cell is selected /// </summary> /// <param name="p_Table">Table instance</param> /// <param name="p_Row">Row index</param> public void DidSelectCellWithIdxEvent(HMUI.TableView p_Table, int p_Row) { if (m_SongPreviewPlayer == null || !m_SongPreviewPlayer || !PlayPreviewAudio || p_Row > Data.Count) { return; } /// Fetch song entry var l_SongRowData = Data[p_Row]; /// Hide if invalid song if (l_SongRowData == null || l_SongRowData.Invalid) { return; } if (l_SongRowData.CustomLevel != null && SongCore.Loader.CustomLevels.ContainsKey(l_SongRowData.CustomLevel.customLevelPath)) { if (AudioClipCache.TryGetValue(l_SongRowData.GetLevelHash(), out var l_AudioClip)) { m_SongPreviewPlayer.CrossfadeTo(l_AudioClip, l_SongRowData.CustomLevel.previewStartTime, l_SongRowData.CustomLevel.previewDuration, PreviewAudioVolume); } else { l_SongRowData.CustomLevel.GetPreviewAudioClipAsync(CancellationToken.None).ContinueWith(x => { if (x.IsCompleted && x.Status == TaskStatus.RanToCompletion) { Unity.MainThreadInvoker.Enqueue(() => { if (!AudioClipCache.ContainsKey(l_SongRowData.GetLevelHash())) { AudioClipCache.Add(l_SongRowData.GetLevelHash(), x.Result); } m_SongPreviewPlayer.CrossfadeTo(x.Result, l_SongRowData.CustomLevel.previewStartTime, l_SongRowData.CustomLevel.previewDuration, PreviewAudioVolume); }); } }); } } else { /// Stop preview music if any m_SongPreviewPlayer.CrossfadeToDefault(); } }
public void OnMenuSceneLoadedFresh() { // get view controller which will contain our buttons RectTransform viewControllersContainer = FindObjectsOfType <RectTransform>().First(x => x.name == "ViewControllers"); ButtonParentViewController = viewControllersContainer.GetComponentInChildren <DismissableNavigationController>(true); _levelsTableViewContainer = viewControllersContainer.GetComponentInChildren <LevelPackLevelsTableView>(true); _levelsTableView = _levelsTableViewContainer.GetPrivateField <TableView>("_tableView"); LevelsViewController = viewControllersContainer.GetComponentInChildren <LevelPackLevelsViewController>(true); var levelPacksViewController = viewControllersContainer.GetComponentInChildren <LevelPacksViewController>(true); levelPacksViewController.didSelectPackEvent += LevelPackSelected; Button soloFreePlayButton = Resources.FindObjectsOfTypeAll <Button>().First(x => x.name == "SoloFreePlayButton"); Button partyFreePlayButton = Resources.FindObjectsOfTypeAll <Button>().First(x => x.name == "PartyFreePlayButton"); Button campaignButton = Resources.FindObjectsOfTypeAll <Button>().First(x => x.name == "CampaignButton"); soloFreePlayButton.onClick.AddListener(() => OnModeSelection(FreePlayMode.Solo)); partyFreePlayButton.onClick.AddListener(() => OnModeSelection(FreePlayMode.Party)); campaignButton.onClick.AddListener(() => OnModeSelection(FreePlayMode.Campaign)); if (SongBrowserTweaks.ModLoaded) { // delay building UI until SongBrowser elements are built (after the user selects mode) } else if (BeatSaverDownloaderTweaks.ModLoaded) { StartCoroutine(GetBeatSaverDownloaderButtons()); } else { CreateSearchButton(DefaultSearchButtonPosition, DefaultButtonSize); CreateFilterButton(DefaultFilterButtonPosition, DefaultButtonSize); CreateClearButton(DefaultClearButtonPosition, DefaultButtonSize); ToggleButtonsActive(false); } }
//////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// /// <summary> /// Build cell /// </summary> /// <param name="p_TableView">Table view instance</param> /// <param name="p_Index">Cell index</param> /// <returns></returns> public HMUI.TableCell CellForIdx(HMUI.TableView p_TableView, int p_Index) { LevelListTableCell l_Cell = GetTableCell(); TextMeshProUGUI l_Text = l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songNameText"); TextMeshProUGUI l_SubText = l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songAuthorText"); l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_favoritesBadgeImage").gameObject.SetActive(false); var l_HoverHint = l_Cell.gameObject.GetComponent <HMUI.HoverHint>(); if (l_HoverHint == null || !l_HoverHint) { l_HoverHint = l_Cell.gameObject.AddComponent <HMUI.HoverHint>(); l_HoverHint.SetField("_hoverHintController", UnityEngine.Resources.FindObjectsOfTypeAll <HMUI.HoverHintController>().First()); } if (l_Cell.gameObject.GetComponent <LocalizedHoverHint>()) { UnityEngine.GameObject.Destroy(l_Cell.gameObject.GetComponent <LocalizedHoverHint>()); } var l_SongEntry = Data[p_Index]; l_SongEntry.Init(); if ((l_SongEntry.BeatSaver_Map != null && !l_SongEntry.BeatSaver_Map.Partial) || l_SongEntry.CustomLevel != null) { var l_HaveSong = l_SongEntry.CustomLevel != null && SongCore.Loader.CustomLevels.ContainsKey(l_SongEntry.CustomLevel.customLevelPath); string l_MapName = ""; string l_MapAuthor = ""; string l_MapSongAuthor = ""; float l_Duration = 0f; float l_BPM = 0f; if (l_SongEntry.CustomLevel != null) { l_MapName = l_SongEntry.CustomLevel.songName; l_MapAuthor = l_SongEntry.CustomLevel.levelAuthorName; l_MapSongAuthor = l_SongEntry.CustomLevel.songAuthorName; l_BPM = l_SongEntry.CustomLevel.beatsPerMinute; l_Duration = l_SongEntry.CustomLevel.songDuration; } else { var l_FirstDiff = l_SongEntry.BeatSaver_Map.Metadata.Characteristics.First().Difficulties.Where(x => x.Value.HasValue).LastOrDefault(); l_MapName = l_SongEntry.BeatSaver_Map.Name; l_MapAuthor = l_SongEntry.BeatSaver_Map.Metadata.LevelAuthorName; l_MapSongAuthor = l_SongEntry.BeatSaver_Map.Metadata.SongAuthorName; l_BPM = l_SongEntry.BeatSaver_Map.Metadata.BPM; l_Duration = l_FirstDiff.Value.Value.Length; } string l_Title = l_SongEntry.TitlePrefix + (l_SongEntry.TitlePrefix.Length != 0 ? " " : "") + (l_HaveSong ? "<#7F7F7F>" : "") + l_MapName; string l_SubTitle = l_MapAuthor + " [" + l_MapSongAuthor + "]"; if (l_Title.Length > (28 + (l_HaveSong ? "<#7F7F7F>".Length : 0))) { l_Title = l_Title.Substring(0, 28 + (l_HaveSong ? "<#7F7F7F>".Length : 0)) + "..."; } if (l_SubTitle.Length > 28) { l_SubTitle = l_SubTitle.Substring(0, 28) + "..."; } l_Text.text = l_Title; l_SubText.text = l_SubTitle; var l_BPMText = l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songBpmText"); l_BPMText.gameObject.SetActive(true); l_BPMText.text = ((int)l_BPM).ToString(); var l_DurationText = l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songDurationText"); l_DurationText.gameObject.SetActive(true); l_DurationText.text = l_Duration >= 0.0 ? $"{Math.Floor((double)l_Duration / 60):N0}:{Math.Floor((double)l_Duration % 60):00}" : "--"; l_Cell.transform.Find("BpmIcon").gameObject.SetActive(true); if (l_SongEntry.Cover != null) { l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = l_SongEntry.Cover; } else if (CoverCache.TryGetValue(l_SongEntry.GetLevelHash(), out var l_Cover)) { l_SongEntry.Cover = l_Cover; l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = l_SongEntry.Cover; OnCoverFetched?.Invoke(l_Cell.idx, l_SongEntry); } else { l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = m_DefaultCover; if (l_HaveSong) { var l_CoverTask = l_SongEntry.CustomLevel.GetCoverImageAsync(CancellationToken.None); _ = l_CoverTask.ContinueWith(p_CoverTaskResult => { if (l_Cell.idx >= Data.Count || l_SongEntry != Data[l_Cell.idx]) { return; } Unity.MainThreadInvoker.Enqueue(() => { /// Update infos l_SongEntry.Cover = p_CoverTaskResult.Result; /// Cache cover if (!CoverCache.ContainsKey(l_SongEntry.GetLevelHash())) { CoverCache.Add(l_SongEntry.GetLevelHash(), l_SongEntry.Cover); } if (l_Cell.idx < Data.Count && l_SongEntry == Data[l_Cell.idx]) { l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = l_SongEntry.Cover; l_Cell.RefreshVisuals(); OnCoverFetched?.Invoke(l_Cell.idx, l_SongEntry); } }); }); } else if (l_SongEntry.BeatSaver_Map != null) { /// Fetch cover var l_CoverTask = l_SongEntry.BeatSaver_Map.FetchCoverImage(); _ = l_CoverTask.ContinueWith(p_CoverTaskResult => { if (l_Cell.idx >= Data.Count || l_SongEntry != Data[l_Cell.idx]) { return; } Unity.MainThreadInvoker.Enqueue(() => { var l_Texture = Unity.Texture2D.CreateFromRaw(p_CoverTaskResult.Result); if (l_Texture != null) { l_SongEntry.Cover = UnityEngine.Sprite.Create(l_Texture, new UnityEngine.Rect(0, 0, l_Texture.width, l_Texture.height), new UnityEngine.Vector2(0.5f, 0.5f), 100); /// Cache cover if (!CoverCache.ContainsKey(l_SongEntry.GetLevelHash())) { CoverCache.Add(l_SongEntry.GetLevelHash(), l_SongEntry.Cover); } if (l_Cell.idx < Data.Count && l_SongEntry == Data[l_Cell.idx]) { l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = l_SongEntry.Cover; l_Cell.RefreshVisuals(); OnCoverFetched?.Invoke(l_Cell.idx, l_SongEntry); } } }); }); } } } else if (l_SongEntry.BeatSaver_Map != null && l_SongEntry.BeatSaver_Map.Partial) { l_Text.text = "Loading from BeatSaver..."; l_SubText.text = ""; l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songBpmText").gameObject.SetActive(false); l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songDurationText").gameObject.SetActive(false); l_Cell.transform.Find("BpmIcon").gameObject.SetActive(false); l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = m_DefaultCover; } else { l_Text.text = "<#FF0000>Invalid song"; l_SubText.text = l_SongEntry.CustomLevel != null?l_SongEntry.CustomLevel.levelID.Replace("custom_level_", "") : ""; l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songBpmText").gameObject.SetActive(false); l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songDurationText").gameObject.SetActive(false); l_Cell.transform.Find("BpmIcon").gameObject.SetActive(false); l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = m_DefaultCover; } if (!string.IsNullOrEmpty(l_SongEntry.HoverHint)) { var l_HoverHintText = l_SongEntry.HoverHint; if (l_SongEntry.HoverHintTimeArg.HasValue && l_HoverHintText.Contains("$$time$$")) { var l_Replace = ""; var l_Elapsed = Misc.Time.UnixTimeNow() - Misc.Time.ToUnixTime(l_SongEntry.HoverHintTimeArg.Value); if (l_Elapsed < (60 * 60)) { l_Replace = Math.Max(1, l_Elapsed / 60).ToString() + " minute(s) ago"; } else if (l_Elapsed < (60 * 60 * 24)) { l_Replace = Math.Max(1, l_Elapsed / (60 * 60)).ToString() + " hour(s) ago"; } else { l_Replace = Math.Max(1, l_Elapsed / (60 * 60 * 24)).ToString() + " day(s) ago"; } l_HoverHintText = l_HoverHintText.Replace("$$time$$", l_Replace); } l_HoverHint.enabled = true; l_HoverHint.text = l_HoverHintText; } else { l_HoverHint.enabled = false; } return(l_Cell); }