Pārlūkot izejas kodu

Support filtering downloader level packs. (#89)

* Allow filtering any level pack.
Create a level pack clone to manage the filtering. 
Inspired by EnhancedSearch.
Halsafar 5 gadi atpakaļ
vecāks
revīzija
944c5561f6

+ 26 - 61
SongBrowserPlugin/DataAccess/SongBrowserModel.cs

@@ -17,6 +17,8 @@ namespace SongBrowser
 {
     public class SongBrowserModel
     {
+        public const string FilteredSongsPackId = "SongBrowser_FilteredSongPack";
+
         private readonly String CUSTOM_SONGS_DIR = Path.Combine("Beat Saber_Data", "CustomLevels");
 
         private readonly DateTime EPOCH = new DateTime(1970, 1, 1);
@@ -343,42 +345,9 @@ namespace SongBrowser
         }
 
         /// <summary>
-        /// Overwrite the current level pack.
-        /// </summary>
-        private void OverwriteCurrentLevelPack(IBeatmapLevelPack pack, List<IPreviewBeatmapLevel> sortedLevels)
-        {
-            Logger.Debug("Overwriting levelPack [{0}] beatmapLevelCollection.levels", pack);
-            if (pack.packID == PluginConfig.CUSTOM_SONG_LEVEL_PACK_ID || (pack as SongCoreCustomBeatmapLevelPack) != null)
-            {
-                Logger.Debug("Overwriting SongCore Level Pack collection...");
-                var newLevels = sortedLevels.Select(x => x as CustomPreviewBeatmapLevel);
-                ReflectionUtil.SetPrivateField(pack.beatmapLevelCollection, "_customPreviewBeatmapLevels", newLevels.ToArray());
-            }
-            else
-            {
-                // Hack to see if level pack is purchased or not.
-                BeatmapLevelPackSO beatmapLevelPack = pack as BeatmapLevelPackSO;
-                if ((pack as BeatmapLevelPackSO) != null)
-                {
-                    Logger.Debug("Owned level pack...");
-                    var newLevels = sortedLevels.Select(x => x as BeatmapLevelSO);
-                    ReflectionUtil.SetPrivateField(pack.beatmapLevelCollection, "_beatmapLevels", newLevels.ToArray());
-                }
-                else
-                {
-                    Logger.Debug("Unowned DLC Detected...");
-                    var newLevels = sortedLevels.Select(x => x as PreviewBeatmapLevelSO);
-                    ReflectionUtil.SetPrivateField(pack.beatmapLevelCollection, "_beatmapLevels", newLevels.ToArray());
-                }
-
-                Logger.Debug("Overwriting Regular Collection...");
-            }
-        }
-
-        /// <summary>
         /// Sort the song list based on the settings.
         /// </summary>
-        public void ProcessSongList(IBeatmapLevelPack pack)
+        public void ProcessSongList(LevelPackLevelsViewController levelsViewController)
         {
             Logger.Trace("ProcessSongList()");
 
@@ -386,35 +355,23 @@ namespace SongBrowser
             List<IPreviewBeatmapLevel> filteredSongs = null;
             List<IPreviewBeatmapLevel> sortedSongs = null;
 
-            // This has come in handy many times for debugging issues with Newest.
-            /*foreach (BeatmapLevelSO level in _originalSongs)
-            {
-                if (_levelIdToCustomLevel.ContainsKey(level.levelID))
-                {
-                    Logger.Debug("HAS KEY {0}: {1}", _levelIdToCustomLevel[level.levelID].customSongInfo.path, level.levelID);
-                }
-                else
-                {
-                    Logger.Debug("Missing KEY: {0}", level.levelID);
-                }
-            }*/
-
             // Abort
-            if (pack == null)
+            if (levelsViewController.levelPack == null)
             {
                 Logger.Debug("Cannot process songs yet, no level pack selected...");
                 return;
             }
             
             // fetch unsorted songs.
+            // playlists always use customsongs
             if (this._settings.filterMode == SongFilterMode.Playlist && this.CurrentPlaylist != null)
             {
                 unsortedSongs = null;
             }
             else
             {
-                Logger.Debug("Using songs from level pack: {0}", pack.packID);
-                unsortedSongs = pack.beatmapLevelCollection.beatmapLevels.ToList();
+                Logger.Debug("Using songs from level pack: {0}", levelsViewController.levelPack.packID);
+                unsortedSongs = levelsViewController.levelPack.beatmapLevelCollection.beatmapLevels.ToList();
             }
 
             // filter
@@ -424,13 +381,13 @@ namespace SongBrowser
             switch (_settings.filterMode)
             {
                 case SongFilterMode.Favorites:
-                    filteredSongs = FilterFavorites(pack);
+                    filteredSongs = FilterFavorites();
                     break;
                 case SongFilterMode.Search:
                     filteredSongs = FilterSearch(unsortedSongs);
                     break;
                 case SongFilterMode.Playlist:
-                    filteredSongs = FilterPlaylist(pack);
+                    filteredSongs = FilterPlaylist();
                     break;
                 case SongFilterMode.Ranked:
                     filteredSongs = FilterRanked(unsortedSongs, true, false);
@@ -440,7 +397,7 @@ namespace SongBrowser
                     break;
                 case SongFilterMode.Custom:
                     Logger.Info("Song filter mode set to custom. Deferring filter behaviour to another mod.");
-                    filteredSongs = CustomFilterHandler != null ? CustomFilterHandler.Invoke(pack) : unsortedSongs;
+                    filteredSongs = CustomFilterHandler != null ? CustomFilterHandler.Invoke(levelsViewController.levelPack) : unsortedSongs;
                     break;
                 case SongFilterMode.None:
                 default:
@@ -508,7 +465,15 @@ namespace SongBrowser
             stopwatch.Stop();
             Logger.Info("Sorting songs took {0}ms", stopwatch.ElapsedMilliseconds);
 
-            this.OverwriteCurrentLevelPack(pack, sortedSongs);
+            // Asterisk the pack name so it is identifable as filtered.
+            var packName = levelsViewController.levelPack.packName;
+            if (!packName.EndsWith("*") && _settings.filterMode != SongFilterMode.None)
+            {
+                packName += "*";
+            }
+            BeatmapLevelPack levelPack = new BeatmapLevelPack(SongBrowserModel.FilteredSongsPackId, packName, levelsViewController.levelPack.coverImage, new BeatmapLevelCollection(sortedSongs.ToArray()));
+            levelsViewController.SetData(levelPack);
+
             //_sortedSongs.ForEach(x => Logger.Debug(x.levelID));
         }
 
@@ -516,14 +481,14 @@ namespace SongBrowser
         /// For now the editing playlist will be considered the favorites playlist.
         /// Users can edit the settings file themselves.
         /// </summary>
-        private List<IPreviewBeatmapLevel> FilterFavorites(IBeatmapLevelPack pack)
+        private List<IPreviewBeatmapLevel> FilterFavorites()
         {
             Logger.Info("Filtering song list as favorites playlist...");
             if (this.CurrentEditingPlaylist != null)
             {
                 this.CurrentPlaylist = this.CurrentEditingPlaylist;
             }
-            return this.FilterPlaylist(pack);
+            return this.FilterPlaylist();
         }
 
         /// <summary>
@@ -569,7 +534,7 @@ namespace SongBrowser
         /// </summary>
         /// <param name="pack"></param>
         /// <returns></returns>
-        private List<IPreviewBeatmapLevel> FilterPlaylist(IBeatmapLevelPack pack)
+        private List<IPreviewBeatmapLevel> FilterPlaylist()
         {
             // bail if no playlist, usually means the settings stored one the user then moved.
             if (this.CurrentPlaylist == null)
@@ -584,12 +549,12 @@ namespace SongBrowser
 
             Logger.Debug("Filtering songs for playlist: {0}", this.CurrentPlaylist.playlistTitle);
 
-            Dictionary<String, IPreviewBeatmapLevel> levelDict = new Dictionary<string, IPreviewBeatmapLevel>();
-            foreach (var level in pack.beatmapLevelCollection.beatmapLevels)
+            Dictionary<String, CustomPreviewBeatmapLevel> levelDict = new Dictionary<string, CustomPreviewBeatmapLevel>();
+            foreach (var level in SongCore.Loader.CustomLevels)
             {
-                if (!levelDict.ContainsKey(level.levelID))
+                if (!levelDict.ContainsKey(level.Value.levelID))
                 {
-                    levelDict.Add(level.levelID, level);
+                    levelDict.Add(level.Value.levelID, level.Value);
                 }               
             }
 

+ 31 - 22
SongBrowserPlugin/UI/Browser/SongBrowserUI.cs

@@ -69,6 +69,8 @@ namespace SongBrowser.UI
         
         private Sprite _currentAddFavoriteButtonSprite;
 
+        private IBeatmapLevelPack _lastLevelPack;
+
         // Model
         private SongBrowserModel _model;
 
@@ -230,7 +232,7 @@ namespace SongBrowser.UI
             _filterByDisplay = _beatUi.LevelPackLevelsViewController.CreateUIButton("ApplyButton", new Vector2(curX, buttonY), new Vector2(outerButtonWidth, buttonHeight), () =>
             {
                 _model.Settings.filterMode = SongFilterMode.None;
-                SongCore.Loader.Instance.RefreshLevelPacks();
+                CancelFilter();
                 RefreshSongUI();
             }, "");
             _filterByDisplay.SetButtonTextSize(displayButtonFontSize);
@@ -504,8 +506,8 @@ namespace SongBrowser.UI
             _beatUi.LevelDetailViewController.didChangeDifficultyBeatmapEvent -= OnDidChangeDifficultyEvent;
             _beatUi.LevelDetailViewController.didChangeDifficultyBeatmapEvent += OnDidChangeDifficultyEvent;
 
-            _beatUi.LevelPacksTableView.didSelectPackEvent -= _levelPacksTableView_didSelectPackEvent;
-            _beatUi.LevelPacksTableView.didSelectPackEvent += _levelPacksTableView_didSelectPackEvent;
+            //_beatUi.LevelPacksTableView.didSelectPackEvent -= _levelPacksTableView_didSelectPackEvent;
+            //_beatUi.LevelPacksTableView.didSelectPackEvent += _levelPacksTableView_didSelectPackEvent;
             _beatUi.LevelPackViewController.didSelectPackEvent -= _levelPackViewController_didSelectPackEvent;
             _beatUi.LevelPackViewController.didSelectPackEvent += _levelPackViewController_didSelectPackEvent;
 
@@ -557,7 +559,7 @@ namespace SongBrowser.UI
                 return;
             }
 
-            this._model.ProcessSongList(_beatUi.GetCurrentSelectedLevelPack());
+            this._model.ProcessSongList(_beatUi.LevelPackLevelsViewController);
         }
 
         /// <summary>
@@ -567,7 +569,7 @@ namespace SongBrowser.UI
         {
             Logger.Debug("Cancelling filter.");
             _model.Settings.filterMode = SongFilterMode.None;
-            SongCore.Loader.Instance.RefreshLevelPacks();
+            _beatUi.LevelPackLevelsViewController.SetData(_lastLevelPack);
         }
 
         /// <summary>
@@ -592,7 +594,7 @@ namespace SongBrowser.UI
                 bool didUpdateLevelPack = this.UpdateLevelPackSelection();
                 if (!didUpdateLevelPack)
                 {
-                    _model.ProcessSongList(_beatUi.GetCurrentSelectedLevelPack());
+                    ProcessSongList();
                 }
                 _beatUi.SelectAndScrollToLevel(_beatUi.LevelPackLevelsTableView, _model.LastSelectedLevelId);
                 RefreshQuickScrollButtons();
@@ -629,28 +631,33 @@ namespace SongBrowser.UI
         /// </summary>
         /// <param name="arg1"></param>
         /// <param name="arg2"></param>
-        private void _levelPackViewController_didSelectPackEvent(LevelPacksViewController arg1, IBeatmapLevelPack arg2)
+        private void _levelPackViewController_didSelectPackEvent(LevelPacksViewController arg1, IBeatmapLevelPack levelPack)
         {
-            Logger.Trace("_levelPackViewController_didSelectPackEvent(arg2={0})", arg2);
+            Logger.Trace("_levelPackViewController_didSelectPackEvent(levelPack={0})", levelPack);
 
             try
             {
+                if (levelPack.packID != SongBrowserModel.FilteredSongsPackId)
+                {
+                    _lastLevelPack = levelPack;
+                }
+
                 // reset filter mode always here
-                if (this._model.Settings.currentLevelPackId != arg2.packID)
+                /*if (this._model.Settings.currentLevelPackId != levelPack.packID)
                 {
                     this._model.Settings.filterMode = SongFilterMode.None;
-                }
+                }*/
 
                 // save level pack
-                this._model.Settings.currentLevelPackId = arg2.packID;
+                this._model.Settings.currentLevelPackId = levelPack.packID;
                 this._model.Settings.Save();
 
-                this._model.ProcessSongList(arg2);
+                ProcessSongList();
 
                 // trickery to handle Downloader playlist level packs
                 // We need to avoid scrolling to a level and then select the header
                 bool scrollToLevel = true;
-                if (arg2.packID.Contains("Playlist_"))
+                if (levelPack.packID.Contains("Playlist_"))
                 {
                     scrollToLevel = false;
                 }
@@ -675,7 +682,7 @@ namespace SongBrowser.UI
             _model.Settings.filterMode = SongFilterMode.None;
             _model.Settings.Save();
 
-            SongCore.Loader.Instance.RefreshLevelPacks();
+            CancelFilter();
             ProcessSongList();
             RefreshSongUI();
         }
@@ -724,17 +731,19 @@ namespace SongBrowser.UI
         {
             Logger.Debug($"FilterButton {mode} clicked.");
 
-            // TODO - Downloader level pack support - need a way to refresh downloader level packs.
-
-            // Every filter will lead to needing a refresh.
-            SongCore.Loader.Instance.RefreshLevelPacks();
+            if (_lastLevelPack == null || _beatUi.LevelPackLevelsViewController.levelPack.packID != SongBrowserModel.FilteredSongsPackId)
+            {
+                _lastLevelPack = _beatUi.LevelPackLevelsViewController.levelPack;
+            }
 
-            // Always select the custom level pack - TODO - Downloader level pack support - Don't always do this
-            var pack = _beatUi.GetCurrentSelectedLevelPack();
-            if (pack != null && !pack.packID.Equals(PluginConfig.CUSTOM_SONG_LEVEL_PACK_ID))
+            if (mode == SongFilterMode.Favorites || mode == SongFilterMode.Playlist)
             {
                 _beatUi.SelectLevelPack(PluginConfig.CUSTOM_SONG_LEVEL_PACK_ID);
             }
+            else
+            {
+                _beatUi.LevelPackLevelsViewController.SetData(_lastLevelPack);
+            }
 
             // If selecting the same filter, cancel
             if (_model.Settings.filterMode == mode)
@@ -1070,7 +1079,7 @@ namespace SongBrowser.UI
 
                     if (_model.Settings.filterMode == SongFilterMode.Favorites)
                     {
-                        this._model.ProcessSongList(_beatUi.GetCurrentSelectedLevelPack());
+                        ProcessSongList();
                         this.RefreshSongList();
                     }
                 }