Quellcode durchsuchen

#102, #112: Playlist support!
Rename Browser setting levelPackId. Now storing level collection name rather than pack id.
Purge IBeatMapLevelPack usage. Replace with IAnnotatedBeatmapLevelCollection.
Only hide the UI when viewing preview packs now.
Template for beatmod release.
Version bump.
Clean up.
Fetch AnnotatedBeatMapLevelViewController.

Stephen Damm vor 4 Jahren
Ursprung
Commit
d0317cd805

+ 2 - 2
BeatModsReleaseTemplate.txt

@@ -1,8 +1,8 @@
 SongBrowser
 
-6.0.2
+6.0.6
 
-SongCore@2.7.2,SongDataCore@1.1.5
+SongCore@2.9.0,SongDataCore@1.3.3
 
 Adds various sorting and filtering methods to the UI. Search, favorites, ranked, and unranked filters. Sort by BeatSaver and ScoreSaber statistics. Adds PP and other extra stats to the stat panel.
 

+ 15 - 16
SongBrowserPlugin/DataAccess/SongBrowserModel.cs

@@ -14,7 +14,8 @@ namespace SongBrowser
 {
     public class SongBrowserModel
     {
-        public static readonly string FilteredSongsPackId = CustomLevelLoader.kCustomLevelPackPrefixId + "SongBrowser_FilteredSongPack";
+        public static readonly string FilteredSongsCollectionName = CustomLevelLoader.kCustomLevelPackPrefixId + "SongBrowser_FilteredSongPack";
+        public static readonly string PlaylistSongsCollectionName = "SongBrowser_PlaylistPack";
 
         private readonly String CUSTOM_SONGS_DIR = Path.Combine("Beat Saber_Data", "CustomLevels");
 
@@ -30,7 +31,7 @@ namespace SongBrowser
 
         public BeatmapCharacteristicSO CurrentBeatmapCharacteristicSO;
 
-        public static Func<IBeatmapLevelPack, List<IPreviewBeatmapLevel>> CustomFilterHandler;
+        public static Func<IAnnotatedBeatmapLevelCollection, List<IPreviewBeatmapLevel>> CustomFilterHandler;
         public static Action<Dictionary<string, CustomPreviewBeatmapLevel>> didFinishProcessingSongs;
 
         public bool SortWasMissingData { get; private set; } = false;
@@ -176,11 +177,11 @@ namespace SongBrowser
         /// <summary>
         /// SongLoader doesn't fire event when we delete a song.
         /// </summary>
-        /// <param name="levelPack"></param>
+        /// <param name="levelCollection"></param>
         /// <param name="levelId"></param>
-        public void RemoveSongFromLevelPack(IBeatmapLevelPack levelPack, String levelId)
+        public void RemoveSongFromLevelCollection(IAnnotatedBeatmapLevelCollection levelCollection, String levelId)
         {
-            levelPack.beatmapLevelCollection.beatmapLevels.ToList().RemoveAll(x => x.levelID == levelId);
+            levelCollection.beatmapLevelCollection.beatmapLevels.ToList().RemoveAll(x => x.levelID == levelId);
         }
 
         /// <summary>
@@ -208,7 +209,7 @@ namespace SongBrowser
         /// <summary>
         /// Sort the song list based on the settings.
         /// </summary>
-        public void ProcessSongList(IBeatmapLevelPack selectedLevelPack, LevelCollectionViewController levelCollectionViewController, LevelSelectionNavigationController navController)
+        public void ProcessSongList(IAnnotatedBeatmapLevelCollection selectedBeatmapCollection, LevelCollectionViewController levelCollectionViewController, LevelSelectionNavigationController navController)
         {
             Logger.Trace("ProcessSongList()");
 
@@ -217,14 +218,14 @@ namespace SongBrowser
             List<IPreviewBeatmapLevel> sortedSongs = null;
 
             // Abort
-            if (selectedLevelPack == null)
+            if (selectedBeatmapCollection == null)
             {
-                Logger.Debug("Cannot process songs yet, no level pack selected...");
+                Logger.Debug("Cannot process songs yet, no level collection selected...");
                 return;
             }
             
-            Logger.Debug("Using songs from level pack: {0}", selectedLevelPack.packID);
-            unsortedSongs = selectedLevelPack.beatmapLevelCollection.beatmapLevels.ToList();            
+            Logger.Debug("Using songs from level collection: {0}", selectedBeatmapCollection.collectionName);
+            unsortedSongs = selectedBeatmapCollection.beatmapLevelCollection.beatmapLevels.ToList();
 
             // filter
             Logger.Debug($"Starting filtering songs by {_settings.filterMode}");
@@ -246,7 +247,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(selectedLevelPack) : unsortedSongs;
+                    filteredSongs = CustomFilterHandler != null ? CustomFilterHandler.Invoke(selectedBeatmapCollection) : unsortedSongs;
                     break;
                 case SongFilterMode.None:
                 default:
@@ -313,18 +314,16 @@ namespace SongBrowser
             stopwatch.Stop();
             Logger.Info("Sorting songs took {0}ms", stopwatch.ElapsedMilliseconds);
 
+            // Still hacking in a custom level pack
             // Asterisk the pack name so it is identifable as filtered.
-            var packName = selectedLevelPack.packName;
+            var packName = selectedBeatmapCollection.collectionName;
             if (!packName.EndsWith("*") && _settings.filterMode != SongFilterMode.None)
             {
                 packName += "*";
             }
-            BeatmapLevelPack levelPack = new BeatmapLevelPack(SongBrowserModel.FilteredSongsPackId, packName, selectedLevelPack.shortPackName, selectedLevelPack.coverImage, new BeatmapLevelCollection(sortedSongs.ToArray()));
+            BeatmapLevelPack levelPack = new BeatmapLevelPack(SongBrowserModel.FilteredSongsCollectionName, packName, selectedBeatmapCollection.collectionName, selectedBeatmapCollection.coverImage, new BeatmapLevelCollection(sortedSongs.ToArray()));
 
             GameObject _noDataGO = levelCollectionViewController.GetPrivateField<GameObject>("_noDataInfoGO");
-            //string _headerText = tableView.GetPrivateField<string>("_headerText");
-            //Sprite _headerSprite = tableView.GetPrivateField<Sprite>("_headerSprite");
-
             bool _showPlayerStatsInDetailView = navController.GetPrivateField<bool>("_showPlayerStatsInDetailView");
             bool _showPracticeButtonInDetailView = navController.GetPrivateField<bool>("_showPracticeButtonInDetailView");
 

+ 6 - 6
SongBrowserPlugin/DataAccess/SongBrowserSettings.cs

@@ -73,7 +73,7 @@ namespace SongBrowser.DataAccess
         public static readonly XmlSerializer SettingsSerializer = new XmlSerializer(typeof(SongBrowserSettings));
         public static readonly String DefaultConvertedFavoritesPlaylistName = "SongBrowserPluginFavorites.json";
         public static readonly String MigratedFavoritesPlaylistName = "SongBrowserPluginFavorites_Migrated.json";
-        public static readonly String CUSTOM_SONG_LEVEL_PACK_ID = "custom_levelpack_CustomLevels";
+        public static readonly String CUSTOM_SONGS_LEVEL_COLLECTION_NAME = "Custom Levels";
 
         public SongSortMode sortMode = default(SongSortMode);
         public SongFilterMode filterMode = default(SongFilterMode);
@@ -82,7 +82,7 @@ namespace SongBrowser.DataAccess
 
         public String currentLevelId = default(String);
         public String currentDirectory = default(String);
-        public String currentLevelPackId = default(String);
+        public String currentLevelCollectionName = default(String);
 
         public bool randomInstantQueue = false;
         public bool deleteNumberedSongFolder = true;
@@ -191,13 +191,13 @@ namespace SongBrowser.DataAccess
         /// <param name="settings"></param>
         private static void ApplyFixes(SongBrowserSettings settings)
         {
-            if (String.Equals(settings.currentLevelPackId, "CustomMaps"))
+            if (String.Equals(settings.currentLevelCollectionName, "CustomMaps"))
             {
-                settings.currentLevelPackId = "ModdedCustomMaps";
+                settings.currentLevelCollectionName = "ModdedCustomMaps";
             }
-            else if (String.Equals(settings.currentLevelPackId, "ModdedCustomMaps"))
+            else if (String.Equals(settings.currentLevelCollectionName, "ModdedCustomMaps"))
             {
-                settings.currentLevelPackId = SongBrowserSettings.CUSTOM_SONG_LEVEL_PACK_ID;
+                settings.currentLevelCollectionName = SongBrowserSettings.CUSTOM_SONGS_LEVEL_COLLECTION_NAME;
             }
 
             settings.Save();

+ 1 - 1
SongBrowserPlugin/Plugin.cs

@@ -10,7 +10,7 @@ namespace SongBrowser
     [Plugin(RuntimeOptions.SingleStartInit)]
     public class Plugin
     {
-        public const string VERSION_NUMBER = "6.0.5";
+        public const string VERSION_NUMBER = "6.0.6";
         public static Plugin Instance;
         public static IPA.Logging.Logger Log;
 

+ 2 - 2
SongBrowserPlugin/Properties/AssemblyInfo.cs

@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
 // You can specify all the values or you can default the Build and Revision Numbers 
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("6.0.5")]
-[assembly: AssemblyFileVersion("6.0.5")]
+[assembly: AssemblyVersion("6.0.6")]
+[assembly: AssemblyFileVersion("6.0.6")]

+ 2 - 1
SongBrowserPlugin/SongBrowser.csproj

@@ -50,7 +50,8 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>D:\Games\Steam\SteamApps\common\Beat Saber\Beat Saber_Data\Managed\IPA.Loader.dll</HintPath>
     </Reference>
-    <Reference Include="Main">
+    <Reference Include="Main, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
       <HintPath>D:\Games\Steam\SteamApps\common\Beat Saber\Beat Saber_Data\Managed\Main.dll</HintPath>
     </Reference>
     <Reference Include="Newtonsoft.Json.12.0.0.0">

+ 1 - 1
SongBrowserPlugin/SongBrowserApplication.cs

@@ -206,7 +206,7 @@ namespace SongBrowser
             yield return new WaitForEndOfFrame();
 
             _songBrowserUI.UpdateLevelDataModel();
-            _songBrowserUI.UpdateLevelPackSelection();
+            _songBrowserUI.UpdateLevelCollectionSelection();
             _songBrowserUI.RefreshSongList();
         }
     }

+ 77 - 32
SongBrowserPlugin/UI/Browser/BeatSaberUIController.cs

@@ -26,6 +26,8 @@ namespace SongBrowser.DataAccess
         public BeatmapDifficultySegmentedControlController LevelDifficultyViewController;
         public BeatmapCharacteristicSegmentedControlController BeatmapCharacteristicSelectionViewController;
 
+        public AnnotatedBeatmapLevelCollectionsViewController AnnotatedBeatmapLevelCollectionsViewController;
+
         public RectTransform LevelCollectionTableViewTransform;
 
         public Button TableViewPageUpButton;
@@ -62,23 +64,18 @@ namespace SongBrowser.DataAccess
             LevelSelectionNavigationController = LevelSelectionFlowCoordinator.GetPrivateField<LevelSelectionNavigationController>("_levelSelectionNavigationController");
             Logger.Debug("Acquired LevelSelectionNavigationController [{0}]", LevelSelectionNavigationController.GetInstanceID());
 
-            // this is loaded late but available early, grab globally.
             LevelFilteringNavigationController = Resources.FindObjectsOfTypeAll<LevelFilteringNavigationController>().First();
-            //LevelSelectionFlowCoordinator.GetPrivateField<LevelFilteringNavigationController>("_levelFilteringNavigationController");
             Logger.Debug("Acquired LevelFilteringNavigationController [{0}]", LevelFilteringNavigationController.GetInstanceID());
 
-            // grab nav controller elements
             LevelCollectionViewController = LevelSelectionNavigationController.GetPrivateField<LevelCollectionViewController>("_levelCollectionViewController");
             Logger.Debug("Acquired LevelPackLevelsViewController [{0}]", LevelCollectionViewController.GetInstanceID());
 
             LevelDetailViewController = LevelSelectionNavigationController.GetPrivateField<StandardLevelDetailViewController>("_levelDetailViewController");
             Logger.Debug("Acquired StandardLevelDetailViewController [{0}]", LevelDetailViewController.GetInstanceID());
 
-            // grab level collection view controller elements
             LevelCollectionTableView = this.LevelCollectionViewController.GetPrivateField<LevelCollectionTableView>("_levelCollectionTableView");
             Logger.Debug("Acquired LevelPackLevelsTableView [{0}]", LevelCollectionTableView.GetInstanceID());
 
-            // grab letel detail view
             StandardLevelDetailView = LevelDetailViewController.GetPrivateField<StandardLevelDetailView>("_standardLevelDetailView");
             Logger.Debug("Acquired StandardLevelDetailView [{0}]", StandardLevelDetailView.GetInstanceID());
 
@@ -91,6 +88,8 @@ namespace SongBrowser.DataAccess
             LevelCollectionTableViewTransform = LevelCollectionTableView.transform as RectTransform;
             Logger.Debug("Acquired TableViewRectTransform from LevelPackLevelsTableView [{0}]", LevelCollectionTableViewTransform.GetInstanceID());
 
+            AnnotatedBeatmapLevelCollectionsViewController = LevelFilteringNavigationController.GetPrivateField<AnnotatedBeatmapLevelCollectionsViewController>("_annotatedBeatmapLevelCollectionsViewController");
+
             TableView tableView = LevelCollectionTableView.GetPrivateField<TableView>("_tableView");
             TableViewPageUpButton = tableView.GetPrivateField<Button>("_pageUpButton");
             TableViewPageDownButton = tableView.GetPrivateField<Button>("_pageDownButton");
@@ -111,7 +110,7 @@ namespace SongBrowser.DataAccess
         /// Get the currently selected level pack within the LevelPackLevelViewController hierarchy.
         /// </summary>
         /// <returns></returns>
-        public IBeatmapLevelPack GetCurrentSelectedLevelPack()
+        private IBeatmapLevelPack GetCurrentSelectedLevelPack()
         {
             if (LevelSelectionNavigationController == null)
             {
@@ -123,65 +122,111 @@ namespace SongBrowser.DataAccess
         }
 
         /// <summary>
-        /// Get level pack by level pack id.
+        /// Helper to get either or playlist or 
+        /// </summary>
+        /// <returns></returns>
+        public IAnnotatedBeatmapLevelCollection GetCurrentSelectedAnnotatedBeatmapLevelCollection()
+        {
+            IAnnotatedBeatmapLevelCollection collection = GetCurrentSelectedLevelPack();
+            if (collection == null)
+            {
+                collection = GetCurrentSelectedPlaylist();
+            }
+
+            return collection;
+        }
+
+        /// <summary>
+        /// Get the currently selected level collection from playlists.
+        /// </summary>
+        /// <returns></returns>
+        private IPlaylist GetCurrentSelectedPlaylist()
+        {
+            if (AnnotatedBeatmapLevelCollectionsViewController == null)
+            {
+                return null;
+            }
+
+            IPlaylist playlist = AnnotatedBeatmapLevelCollectionsViewController.selectedAnnotatedBeatmapLevelCollection as IPlaylist;
+            return playlist;
+        }
+
+        /// <summary>
+        /// Get level collection by level collection name.
         /// </summary>
-        /// <param name="levelPackId"></param>
+        /// <param name="levelCollectionName"></param>
         /// <returns></returns>
-        public IBeatmapLevelPack GetLevelPackByPackId(String levelPackId)
+        public IAnnotatedBeatmapLevelCollection GetLevelCollectionByName(String levelCollectionName)
         {
-            IBeatmapLevelPack pack = null;
+            IAnnotatedBeatmapLevelCollection levelCollection = null;
+
+            // search level packs
             foreach (IBeatmapLevelPack o in BeatmapLevelsModel.allLoadedBeatmapLevelPackCollection.beatmapLevelPacks)
             {
-                if (String.Equals(o.packID, levelPackId))
+                if (String.Equals(o.collectionName, levelCollectionName))
                 {
-                    pack = o;
+                    levelCollection = o;
+                    break;
                 }
             }
 
-            return pack;
+            // search playlists
+            if (levelCollection == null)
+            {
+                IAnnotatedBeatmapLevelCollection[] _annotatedBeatmapLevelCollections = AnnotatedBeatmapLevelCollectionsViewController.GetPrivateField<IAnnotatedBeatmapLevelCollection[]>("_annotatedBeatmapLevelCollections");
+                foreach (IAnnotatedBeatmapLevelCollection c in _annotatedBeatmapLevelCollections)
+                {
+                    if (String.Equals(c.collectionName, levelCollectionName))
+                    {
+                        levelCollection = c;
+                        break;
+                    }
+                }
+            }
+
+            return levelCollection;
         }
 
         /// <summary>
-        /// Get Current levels from current level pack.
+        /// Get Current levels from current level collection.
         /// </summary>
         /// <returns></returns>
-        public IPreviewBeatmapLevel[] GetCurrentLevelPackLevels()
+        public IPreviewBeatmapLevel[] GetCurrentLevelCollectionLevels()
         {
-            var levelPack = GetCurrentSelectedLevelPack();
-            if (levelPack == null)
+            var levelCollection = GetCurrentSelectedAnnotatedBeatmapLevelCollection();
+            if (levelCollection == null)
             {
-                Logger.Debug("Current selected level pack is null for some reason...");
+                Logger.Debug("Current selected level collection is null for some reason...");
                 return null;
             }
             
-            return levelPack.beatmapLevelCollection.beatmapLevels;
+            return levelCollection.beatmapLevelCollection.beatmapLevels;
         }
 
         /// <summary>
-        /// Select a level pack.
+        /// Select a level collection.
         /// </summary>
-        /// <param name="levelPackId"></param>
-        public void SelectLevelPack(String levelPackId)
+        /// <param name="levelCollectionName"></param>
+        public void SelectLevelCollection(String levelCollectionName)
         {
-            Logger.Trace("SelectLevelPack({0})", levelPackId);
+            Logger.Trace("SelectLevelCollection({0})", levelCollectionName);
 
             try
             {
-                //var levelPacks = GetLevelPackCollection();
-                IBeatmapLevelPack pack = GetLevelPackByPackId(levelPackId);
+                IAnnotatedBeatmapLevelCollection collection = GetLevelCollectionByName(levelCollectionName);
 
-                if (pack == null)
+                if (collection == null)
                 {
-                    Logger.Debug("Could not locate requested level pack...");
+                    Logger.Debug("Could not locate requested level collection...");
                     return;
                 }
 
-                Logger.Info("Selecting level pack: {0}", pack.packID);
+                Logger.Info("Selecting level collection: {0}", collection.collectionName);
 
-                LevelFilteringNavigationController.SelectBeatmapLevelPackOrPlayList(pack, null);
+                LevelFilteringNavigationController.SelectBeatmapLevelPackOrPlayList(collection as IBeatmapLevelPack, collection as IPlaylist);
                 LevelFilteringNavigationController.TabBarDidSwitch();
                
-                Logger.Debug("Done selecting level pack!");
+                Logger.Debug("Done selecting level collection!");
             }
             catch (Exception e)
             {
@@ -217,7 +262,7 @@ namespace SongBrowser.DataAccess
 
             // try to find the index and scroll to it
             int selectedIndex = 0;
-            List<IPreviewBeatmapLevel> levels = GetCurrentLevelPackLevels().ToList();
+            List<IPreviewBeatmapLevel> levels = GetCurrentLevelCollectionLevels().ToList();
             if (levels.Count <= 0)
             {
                 return;
@@ -271,7 +316,7 @@ namespace SongBrowser.DataAccess
             Logger.Info("Refreshing the song list view.");
             try
             {
-                var levels = GetCurrentLevelPackLevels();
+                var levels = GetCurrentLevelCollectionLevels();
                 if (levels == null)
                 {
                     Logger.Info("Nothing to refresh yet.");

+ 87 - 120
SongBrowserPlugin/UI/Browser/SongBrowserUI.cs

@@ -60,7 +60,7 @@ namespace SongBrowser.UI
         private RectTransform _starStatButton;
         private RectTransform _njsStatButton;
 
-        private IBeatmapLevelPack _lastLevelPack;
+        private IAnnotatedBeatmapLevelCollection _lastLevelCollection;
 
         private SongBrowserModel _model;
         public SongBrowserModel Model
@@ -111,7 +111,7 @@ namespace SongBrowser.UI
             Logger.Debug("Done fetching Flow Coordinator for the appropriate mode...");
 
             _beatUi = new DataAccess.BeatSaberUIController(flowCoordinator);
-            _lastLevelPack = null;
+            _lastLevelCollection = null;
 
             // returning to the menu and switching modes could trigger this.
             if (_uiCreated)
@@ -469,7 +469,7 @@ namespace SongBrowser.UI
         /// </summary>
         private void InstallHandlers()
         {
-            // level pack, level, difficulty handlers, characteristics
+            // level collection, level, difficulty handlers, characteristics
             TableView tableView = ReflectionUtil.GetPrivateField<TableView>(_beatUi.LevelCollectionTableView, "_tableView");
 
             // update stats
@@ -483,11 +483,11 @@ namespace SongBrowser.UI
             _beatUi.LevelDetailViewController.didChangeDifficultyBeatmapEvent += OnDidChangeDifficultyEvent;
 
             // update our view of the game state
-            _beatUi.LevelFilteringNavigationController.didSelectAnnotatedBeatmapLevelCollectionEvent -= _levelFilteringNavController_didSelectPackEvent;
-            _beatUi.LevelFilteringNavigationController.didSelectAnnotatedBeatmapLevelCollectionEvent += _levelFilteringNavController_didSelectPackEvent;
+            _beatUi.LevelFilteringNavigationController.didSelectAnnotatedBeatmapLevelCollectionEvent -= _levelFilteringNavController_didSelectAnnotatedBeatmapLevelCollectionEvent;
+            _beatUi.LevelFilteringNavigationController.didSelectAnnotatedBeatmapLevelCollectionEvent += _levelFilteringNavController_didSelectAnnotatedBeatmapLevelCollectionEvent;
 
-            _beatUi.LevelSelectionNavigationController.didSelectLevelPackEvent -= _levelSelectionNavigationController_didSelectPackEvent;
-            _beatUi.LevelSelectionNavigationController.didSelectLevelPackEvent += _levelSelectionNavigationController_didSelectPackEvent;
+            _beatUi.AnnotatedBeatmapLevelCollectionsViewController.didSelectAnnotatedBeatmapLevelCollectionEvent -= handleDidSelectAnnotatedBeatmapLevelCollection;
+            _beatUi.AnnotatedBeatmapLevelCollectionsViewController.didSelectAnnotatedBeatmapLevelCollectionEvent += handleDidSelectAnnotatedBeatmapLevelCollection;
 
             // Respond to characteristics changes
             _beatUi.BeatmapCharacteristicSelectionViewController.didSelectBeatmapCharacteristicEvent -= OnDidSelectBeatmapCharacteristic;
@@ -502,41 +502,8 @@ namespace SongBrowser.UI
             {
                 StartCoroutine(RefreshQuickScrollButtonsAsync());
             });
-
-            // finished level	
-            //ResultsViewController resultsViewController = _beatUi.LevelSelectionFlowCoordinator.GetPrivateField<ResultsViewController>("_resultsViewController");
-            //resultsViewController.continueButtonPressedEvent += ResultsViewController_continueButtonPressedEvent;
-        }
-
-        /*/// <summary>	
-        /// Handle updating the level pack selection after returning from a song.	
-        /// </summary>SongBrowserPlugin/UI/Browser/SongBrowserUI.cs 	
-        /// <param name="obj"></param>	
-        private void ResultsViewController_continueButtonPressedEvent(ResultsViewController obj)
-        {
-            StartCoroutine(this.UpdateLevelPackSelectionEndOfFrame());
         }
 
-        /// <summary>	
-        /// TODO - evaluate this sillyness...	
-        /// </summary>	
-        /// <returns></returns>	
-        public IEnumerator UpdateLevelPackSelectionEndOfFrame()
-        {
-            yield return new WaitForEndOfFrame();
-
-            try
-            {
-                UpdateLevelPackSelection();
-                _beatUi.SelectAndScrollToLevel(_model.LastSelectedLevelId);
-                RefreshQuickScrollButtons();
-            }
-            catch (Exception e)
-            {
-                Logger.Exception("Exception:", e);
-            }
-        }*/
-
         /// <summary>
         /// Waits for the song UI to be available before trying to update.
         /// </summary>
@@ -611,8 +578,7 @@ namespace SongBrowser.UI
                 return;
             }
 
-            var levelPack = _lastLevelPack;
-            this._model.ProcessSongList(levelPack, _beatUi.LevelCollectionViewController, _beatUi.LevelSelectionNavigationController);
+            this._model.ProcessSongList(_lastLevelCollection, _beatUi.LevelCollectionViewController, _beatUi.LevelSelectionNavigationController);
         }
 
         /// <summary>
@@ -620,59 +586,59 @@ namespace SongBrowser.UI
         /// </summary>
         public void CancelFilter()
         {
-            Logger.Debug($"Cancelling filter, levelPack {_lastLevelPack}");
+            Logger.Debug($"Cancelling filter, levelCollection {_lastLevelCollection}");
             _model.Settings.filterMode = SongFilterMode.None;
 
             GameObject _noDataGO = _beatUi.LevelCollectionViewController.GetPrivateField<GameObject>("_noDataInfoGO");
             string _headerText = _beatUi.LevelCollectionTableView.GetPrivateField<string>("_headerText");
             Sprite _headerSprite = _beatUi.LevelCollectionTableView.GetPrivateField<Sprite>("_headerSprite");
 
-            _beatUi.LevelCollectionViewController.SetData(_lastLevelPack.beatmapLevelCollection, _headerText, _headerSprite, false, _noDataGO);
+            IBeatmapLevelCollection levelCollection = _beatUi.GetCurrentSelectedAnnotatedBeatmapLevelCollection().beatmapLevelCollection;
+            _beatUi.LevelCollectionViewController.SetData(levelCollection, _headerText, _headerSprite, false, _noDataGO);
         }
 
         /// <summary>
-        /// Handler for level pack selection.
+        /// Playlists (fancy name for AnnotatedBeatmapLevelCollection)
         /// </summary>
-        /// <param name="arg1"></param>
-        /// <param name="arg2"></param>
-        private void _levelPacksTableView_didSelectPackEvent(AnnotatedBeatmapLevelCollectionsTableView arg1, IBeatmapLevelPack arg2)
+        /// <param name="annotatedBeatmapLevelCollection"></param>
+        public virtual void handleDidSelectAnnotatedBeatmapLevelCollection(IAnnotatedBeatmapLevelCollection annotatedBeatmapLevelCollection)
         {
-            Logger.Trace("_levelPacksTableView_didSelectPackEvent(arg2={0})", arg2);
-
-            try
-            {
-                RefreshSortButtonUI();
-                RefreshQuickScrollButtons();
-            }
-            catch (Exception e)
-            {
-                Logger.Exception("Exception handling didSelectPackEvent...", e);
-            }
+            Logger.Trace("handleDidSelectAnnotatedBeatmapLevelCollection()");
+            _lastLevelCollection = annotatedBeatmapLevelCollection;
+            Logger.Debug("Selected Level Collection={0}", _lastLevelCollection);
         }
 
         /// <summary>
-        /// Handler for level pack selection, controller.
-        /// Sets the current level pack into the model and updates.
+        /// Handler for level collection selection, controller.
+        /// Sets the current level collection into the model and updates.
         /// </summary>
         /// <param name="arg1"></param>
         /// <param name="arg2"></param>
         /// <param name="arg3"></param>
         /// <param name="arg4"></param>
-        private void _levelFilteringNavController_didSelectPackEvent(LevelFilteringNavigationController arg1, IAnnotatedBeatmapLevelCollection arg2, 
+        private void _levelFilteringNavController_didSelectAnnotatedBeatmapLevelCollectionEvent(LevelFilteringNavigationController arg1, IAnnotatedBeatmapLevelCollection arg2, 
             GameObject arg3, BeatmapCharacteristicSO arg4)
         {
-            Logger.Trace("_levelFilteringNavController_didSelectPackEvent(levelPack={0})", arg2);
+            Logger.Trace("_levelFilteringNavController_didSelectAnnotatedBeatmapLevelCollectionEvent(levelCollection={0})", arg2);
 
-            // Skip the first time - Effectively ignores BeatSaber forcing OST1 on us on first load.
-            if (_lastLevelPack == null)
+            if (arg2 == null)
             {
-                return;
+                // Probably means we transitioned between Music Packs and Playlists
+                arg2 = _beatUi.GetCurrentSelectedAnnotatedBeatmapLevelCollection();
+                if (arg2 == null)
+                {
+                    Logger.Warning("Nothing selected.  This is likely an error.");
+                    return;
+                }
             }
 
-            IBeatmapLevelPack levelPack = arg2 as IBeatmapLevelPack;
-            if (levelPack == null)
+            Logger.Debug("Selected Level Collection={0}", arg2);
+
+            // Do something about preview level packs, they can't be used past this point
+            if (arg2 as PreviewBeatmapLevelPackSO)
             {
-                Logger.Info("Hiding SongBrowser, Playlist mode currently unsupported...");
+                Logger.Info("Hiding SongBrowser, previewing a song pack.");
+                //CancelFilter();
                 Hide();
                 return;
             }
@@ -681,53 +647,49 @@ namespace SongBrowser.UI
                 Show();
             }
 
-            SelectPack(levelPack);
-        }
+            // Skip the first time - Effectively ignores BeatSaber forcing OST1 on us on first load.
+            // Skip when we have a playlist
+            if (_lastLevelCollection == null)
+            {
+                return;
+            }
 
-        /// <summary>
-        /// Dummy method for now.
-        /// </summary>
-        /// <param name="arg1"></param>
-        /// <param name="arg2"></param>
-        private void _levelSelectionNavigationController_didSelectPackEvent(LevelSelectionNavigationController controller, IBeatmapLevelPack levelPack)
-        {
-            Logger.Trace("_levelSelectionNavigationController_didSelectPackEvent(levelPack={0})", levelPack);
-            //SelectPack(levelPack);
+            SelectLevelCollection(arg2);
         }
 
         /// <summary>
-        /// Logic for selecting a level pack.
+        /// Logic for selecting a level collection.
         /// </summary>
         /// <param name="levelPack"></param>
-        public void SelectPack(IBeatmapLevelPack levelPack)
+        public void SelectLevelCollection(IAnnotatedBeatmapLevelCollection levelCollection)
         {
             try
             {
-                if (levelPack == null)
+                if (levelCollection == null)
                 {
-                    Logger.Debug("Invalid level pack, seems to be playlists mode...");
+                    Logger.Debug("No level collection selected...");
                     return;
                 }
 
-                // store the real level pack
-                if (levelPack.packID != SongBrowserModel.FilteredSongsPackId && _lastLevelPack != null)
+                // store the real level collection
+                if (levelCollection.collectionName != SongBrowserModel.FilteredSongsCollectionName && _lastLevelCollection != null)
                 {
-                    Logger.Debug("Recording levelPack: {0}", levelPack.packID);
-                    _lastLevelPack = levelPack;
+                    Logger.Debug("Recording levelCollection: {0}", levelCollection.collectionName);
+                    _lastLevelCollection = levelCollection;
                 }
 
                 // reset level selection
                 _model.LastSelectedLevelId = null;
 
-                // save level packs
-                this._model.Settings.currentLevelPackId = levelPack.packID;
+                // save level collection
+                this._model.Settings.currentLevelCollectionName = levelCollection.collectionName;
                 this._model.Settings.Save();
 
                 StartCoroutine(ProcessSongListEndOfFrame());
             }
             catch (Exception e)
             {
-                Logger.Exception("Exception handling didSelectPackEvent...", e);
+                Logger.Exception("Exception handling SelectLevelCollection...", e);
             }
         }
 
@@ -804,22 +766,27 @@ namespace SongBrowser.UI
         {
             Logger.Debug($"FilterButton {mode} clicked.");
 
-            if (_lastLevelPack == null || _beatUi.GetCurrentSelectedLevelPack().packID != SongBrowserModel.FilteredSongsPackId)
+            var curCollection = _beatUi.GetCurrentSelectedAnnotatedBeatmapLevelCollection();
+            if (_lastLevelCollection == null || 
+                (curCollection != null &&
+                curCollection.collectionName != SongBrowserModel.FilteredSongsCollectionName &&
+                curCollection.collectionName != SongBrowserModel.PlaylistSongsCollectionName))
             {
-                _lastLevelPack = _beatUi.GetCurrentSelectedLevelPack();
+                _lastLevelCollection = _beatUi.GetCurrentSelectedAnnotatedBeatmapLevelCollection();
             }
 
             if (mode == SongFilterMode.Favorites)
             {
-                _beatUi.SelectLevelPack(SongBrowserSettings.CUSTOM_SONG_LEVEL_PACK_ID);
+                _beatUi.SelectLevelCollection(SongBrowserSettings.CUSTOM_SONGS_LEVEL_COLLECTION_NAME);
             }
             else
-            {              
+            {
                 GameObject _noDataGO = _beatUi.LevelCollectionViewController.GetPrivateField<GameObject>("_noDataInfoGO");
                 string _headerText = _beatUi.LevelCollectionTableView.GetPrivateField<string>("_headerText");
                 Sprite _headerSprite = _beatUi.LevelCollectionTableView.GetPrivateField<Sprite>("_headerSprite");
-                
-                _beatUi.LevelCollectionViewController.SetData(_lastLevelPack.beatmapLevelCollection, _headerText, _headerSprite, false, _noDataGO);
+
+                IBeatmapLevelCollection levelCollection = _beatUi.GetCurrentSelectedAnnotatedBeatmapLevelCollection().beatmapLevelCollection;
+                _beatUi.LevelCollectionViewController.SetData(levelCollection, _headerText, _headerSprite, false, _noDataGO);
             }
 
             // If selecting the same filter, cancel
@@ -980,7 +947,7 @@ namespace SongBrowser.UI
                             // determine the index we are deleting so we can keep the cursor near the same spot after
                             // the header counts as an index, so if the index came from the level array we have to add 1.
                             var levelsTableView = _beatUi.LevelCollectionTableView;
-                            List<IPreviewBeatmapLevel> levels = _beatUi.GetCurrentLevelPackLevels().ToList();
+                            List<IPreviewBeatmapLevel> levels = _beatUi.GetCurrentLevelCollectionLevels().ToList();
                             int selectedIndex = levels.FindIndex(x => x.levelID == _beatUi.StandardLevelDetailView.selectedDifficultyBeatmap.level.levelID);
 
                             if (selectedIndex > -1)
@@ -989,7 +956,7 @@ namespace SongBrowser.UI
 
                                 Logger.Info($"Deleting song: {song.customLevelPath}");
                                 SongCore.Loader.Instance.DeleteSong(song.customLevelPath);
-                                this._model.RemoveSongFromLevelPack(_beatUi.GetCurrentSelectedLevelPack(), _beatUi.LevelDetailViewController.selectedDifficultyBeatmap.level.levelID);
+                                this._model.RemoveSongFromLevelCollection(_beatUi.GetCurrentSelectedAnnotatedBeatmapLevelCollection(), _beatUi.LevelDetailViewController.selectedDifficultyBeatmap.level.levelID);
 
                                 int removedLevels = levels.RemoveAll(x => x.levelID == _beatUi.StandardLevelDetailView.selectedDifficultyBeatmap.level.levelID);
                                 Logger.Info("Removed " + removedLevels + " level(s) from song list!");
@@ -1072,7 +1039,7 @@ namespace SongBrowser.UI
         /// <param name="numJumps"></param>
         private void JumpSongList(int numJumps, float segmentPercent)
         {
-            var levels = _beatUi.GetCurrentLevelPackLevels();
+            var levels = _beatUi.GetCurrentLevelCollectionLevels();
             if (levels == null)
             {
                 return;
@@ -1403,44 +1370,44 @@ namespace SongBrowser.UI
         /// <summary>
         /// Logic for fixing BeatSaber's level pack selection bugs.
         /// </summary>
-        public bool UpdateLevelPackSelection()
+        public bool UpdateLevelCollectionSelection()
         {
             if (_uiCreated)
             {
-                IBeatmapLevelPack currentSelected = _beatUi.GetCurrentSelectedLevelPack();
-                Logger.Debug("Current selected level pack: {0}", currentSelected);
+                IAnnotatedBeatmapLevelCollection currentSelected = _beatUi.GetCurrentSelectedAnnotatedBeatmapLevelCollection();
+                Logger.Debug("Current selected level collection: {0}", currentSelected);
 
-                if (String.IsNullOrEmpty(_model.Settings.currentLevelPackId))
+                if (String.IsNullOrEmpty(_model.Settings.currentLevelCollectionName))
                 {
                     if (currentSelected == null)
                     {
-                        Logger.Debug("No level pack selected, acquiring the first available...");
+                        Logger.Debug("No level collection selected, acquiring the first available, likely OST1...");
                         currentSelected = _beatUi.BeatmapLevelsModel.allLoadedBeatmapLevelPackCollection.beatmapLevelPacks[0];
                     }
                 }
-                else if (currentSelected == null || (currentSelected.packID != _model.Settings.currentLevelPackId))
+                else if (currentSelected == null || (currentSelected.collectionName != _model.Settings.currentLevelCollectionName))
                 {
-                    Logger.Debug("Automatically selecting level pack: {0}", _model.Settings.currentLevelPackId);
+                    Logger.Debug("Automatically selecting level collection: {0}", _model.Settings.currentLevelCollectionName);
+                    _beatUi.LevelFilteringNavigationController.didSelectAnnotatedBeatmapLevelCollectionEvent -= _levelFilteringNavController_didSelectAnnotatedBeatmapLevelCollectionEvent;
 
-                    _beatUi.LevelSelectionNavigationController.didSelectLevelPackEvent -= _levelSelectionNavigationController_didSelectPackEvent;
-                    _beatUi.LevelFilteringNavigationController.didSelectAnnotatedBeatmapLevelCollectionEvent -= _levelFilteringNavController_didSelectPackEvent;
-
-                    _lastLevelPack = _beatUi.GetLevelPackByPackId(_model.Settings.currentLevelPackId);
-                    _beatUi.SelectLevelPack(_model.Settings.currentLevelPackId);
-
-                    _beatUi.LevelSelectionNavigationController.didSelectLevelPackEvent += _levelSelectionNavigationController_didSelectPackEvent;
-                    _beatUi.LevelFilteringNavigationController.didSelectAnnotatedBeatmapLevelCollectionEvent += _levelFilteringNavController_didSelectPackEvent;
+                    _lastLevelCollection = _beatUi.GetLevelCollectionByName(_model.Settings.currentLevelCollectionName);
+                    if (_lastLevelCollection as PreviewBeatmapLevelPackSO)
+                    {
+                        Hide();
+                    }
+                    _beatUi.SelectLevelCollection(_model.Settings.currentLevelCollectionName);
+                    _beatUi.LevelFilteringNavigationController.didSelectAnnotatedBeatmapLevelCollectionEvent += _levelFilteringNavController_didSelectAnnotatedBeatmapLevelCollectionEvent;
                 }
 
-                if (_lastLevelPack == null)
+                if (_lastLevelCollection == null)
                 {
-                    if (currentSelected.packID != SongBrowserModel.FilteredSongsPackId)
-                    {                        
-                        _lastLevelPack = currentSelected;
+                    if (currentSelected.collectionName != SongBrowserModel.FilteredSongsCollectionName && currentSelected.collectionName != SongBrowserModel.PlaylistSongsCollectionName)
+                    {
+                        _lastLevelCollection = currentSelected;
                     }
                 }
 
-                Logger.Debug("Last levelPack is: {0}", _lastLevelPack);
+                Logger.Debug("Current Level Collection is: {0}", _lastLevelCollection);
                 ProcessSongList();
             }
 

+ 1 - 1
SongBrowserPlugin/manifest.json

@@ -4,7 +4,7 @@
   "gameVersion": "1.8.0",
   "id": "SongBrowser",
   "name": "Song Browser",
-  "version": "6.0.5",
+  "version": "6.0.6",
   "dependsOn": {
     "SongCore": "^2.9.0",
     "SongDataCore": "^1.3.3"