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);
            }
        }
예제 #3
0
        ////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////

        /// <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);
            }
        }
예제 #5
0
        ////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////

        /// <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);
        }