private void SetupUI() { if (initialized) { return; } _beatmapCharacteristics = Resources.FindObjectsOfTypeAll <BeatmapCharacteristicSO>(); _lastCharacteristic = _beatmapCharacteristics.First(x => x.characteristicName == "Standard"); Resources.FindObjectsOfTypeAll <BeatmapCharacteristicSelectionViewController>().First().didSelectBeatmapCharacteristicEvent += (BeatmapCharacteristicSelectionViewController sender, BeatmapCharacteristicSO selected) => { _lastCharacteristic = selected; }; if (SongLoader.AreSongsLoaded) { _levelCollection = SongLoader.CustomLevelCollectionSO; } else { SongLoader.SongsLoadedEvent += (SongLoader sender, List <CustomLevel> levels) => { _levelCollection = SongLoader.CustomLevelCollectionSO; }; } _levelListViewController = Resources.FindObjectsOfTypeAll <LevelListViewController>().FirstOrDefault(); RectTransform _tableViewRectTransform = _levelListViewController.GetComponentsInChildren <RectTransform>().First(x => x.name == "TableViewContainer"); _tableViewRectTransform.sizeDelta = new Vector2(0f, -35f); //_tableViewRectTransform.anchoredPosition = new Vector2(0f, -2.5f); RectTransform _pageUp = _tableViewRectTransform.GetComponentsInChildren <RectTransform>(true).First(x => x.name == "PageUpButton"); _pageUp.anchoredPosition = new Vector2(0f, -1f); RectTransform _pageDown = _tableViewRectTransform.GetComponentsInChildren <RectTransform>(true).First(x => x.name == "PageDownButton"); _pageDown.anchoredPosition = new Vector2(0f, 1f); _requestButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(0, 30.25f), new Vector2(20f, 6f), RequestsButtonPressed, "Requests"); _requestButton.SetButtonTextSize(3f); _requestButton.ToggleWordWrapping(false); _detailViewController = Resources.FindObjectsOfTypeAll <StandardLevelDetailViewController>().First(x => x.name == "StandardLevelDetailViewController"); //based on https://github.com/halsafar/BeatSaberSongBrowser/blob/master/SongBrowserPlugin/UI/Browser/SongBrowserUI.cs#L192 var statsPanel = _detailViewController.GetComponentsInChildren <CanvasRenderer>(true).First(x => x.name == "LevelParamsPanel"); var statTransforms = statsPanel.GetComponentsInChildren <RectTransform>(); var valueTexts = statsPanel.GetComponentsInChildren <TextMeshProUGUI>().Where(x => x.name == "ValueText").ToList(); foreach (RectTransform r in statTransforms) { if (r.name == "Separator") { continue; } r.sizeDelta = new Vector2(r.sizeDelta.x * 0.85f, r.sizeDelta.y * 0.85f); } _levelListViewController.didSelectLevelEvent += _levelListViewController_didSelectLevelEvent; initialized = true; }
public static CustomLevelCollectionSO ReplaceOriginal(LevelCollectionSO original) { var newCollection = CreateInstance <CustomLevelCollectionSO>(); newCollection._levelList.AddRange(original.levels); newCollection.UpdateArray(); newCollection.ReplaceReferences(); foreach (var originalLevel in original.levels) { if (_standardCharacteristic == null) { _standardCharacteristic = originalLevel.beatmapCharacteristics.FirstOrDefault(x => x.characteristicName == "Standard"); } if (_oneSaberCharacteristic == null) { _oneSaberCharacteristic = originalLevel.beatmapCharacteristics.FirstOrDefault(x => x.characteristicName == "One Saber"); } if (_noArrowsCharacteristic == null) { _noArrowsCharacteristic = originalLevel.beatmapCharacteristics.FirstOrDefault(x => x.characteristicName == "No Arrows"); } } return(newCollection); }
private void FilterPlaylist() { // bail if no playlist, usually means the settings stored one the user then moved. if (this.CurrentPlaylist == null) { Logger.Error("Trying to load a null playlist..."); _filteredSongs = _originalSongs; this.Settings.filterMode = SongFilterMode.None; return; } Logger.Debug("Filtering songs for playlist: {0}", this.CurrentPlaylist.Title); LevelCollectionSO levelCollections = Resources.FindObjectsOfTypeAll <LevelCollectionSO>().FirstOrDefault(); var levels = levelCollections.GetLevelsWithBeatmapCharacteristic(CurrentBeatmapCharacteristicSO); //Dictionary<String, LevelSO> levelDict = levels.Select((val, index) => new { LevelId = val.levelID, Level = val }).ToDictionary(i => i.LevelId, i => i.Level); Dictionary <String, LevelSO> levelDict = new Dictionary <string, LevelSO>(); foreach (LevelSO level in levels) { if (!levelDict.ContainsKey(level.levelID)) { levelDict.Add(level.levelID, level); } } List <LevelSO> songList = new List <LevelSO>(); foreach (PlaylistSong ps in this.CurrentPlaylist.Songs) { if (!String.IsNullOrEmpty(ps.LevelId)) { if (levelDict.ContainsKey(ps.LevelId)) { songList.Add(levelDict[ps.LevelId]); } } else if (!ps.Key.StartsWith("Level_") && _keyToSong.ContainsKey(ps.Key)) { songList.Add(_keyToSong[ps.Key]); } } _originalSongs = songList; _filteredSongs = _originalSongs; Logger.Debug("Playlist filtered song count: {0}", _filteredSongs.Count); }
public static void Init(LevelCollectionSO collection) { if (!Initialized) { Debug.Log("Levels local Path : " + saveFilePath); LevelCollection data = LoadLevelData(); if (data != null && data.localLevelData != null) { LEVELS = new List<LocalLevelData>(); LEVELS = data.localLevelData; Debug.Log("Level Data fetched, updating variables.."); UpdateLevelVariables(collection); Initialized = true; } else { Debug.LogError("Level Collection type is not attached to resource fetched"); } } }
protected override void DidActivate(bool firstActivation, ActivationType activationType) { _beatmapCharacteristics = Resources.FindObjectsOfTypeAll <BeatmapCharacteristicSO>(); _standardCharacteristics = _beatmapCharacteristics.First(x => x.characteristicName == "Standard"); _levelCollection = SongLoader.CustomLevelCollectionSO; if (firstActivation) { _radioNavController = BeatSaberUI.CreateViewController <RoomNavigationController>(); _radioNavController.didFinishEvent += () => { LeaveChannel(); }; _inGameViewController = BeatSaberUI.CreateViewController <InGameScreenViewController>(); _inGameViewController.playPressedEvent += PlayNow_Pressed; _nextSongScreenViewController = BeatSaberUI.CreateViewController <NextSongScreenViewController>(); _nextSongScreenViewController.skipPressedEvent += SkipSong_Pressed; _resultsScreenViewController = BeatSaberUI.CreateViewController <ResultsScreenViewController>(); } ProvideInitialViewControllers(_radioNavController, null, null); }
protected override void DidActivate(bool firstActivation, ActivationType activationType) { _beatmapCharacteristics = Resources.FindObjectsOfTypeAll <BeatmapCharacteristicSO>(); _levelCollection = SongLoader.CustomLevelCollectionSO; if (firstActivation && activationType == ActivationType.AddedToHierarchy) { _serverHubsViewController = BeatSaberUI.CreateViewController <RoomCreationServerHubsListViewController>(); _serverHubsViewController.selectedServerHub += ServerHubSelected; _serverHubsViewController.didFinishEvent += () => { didFinishEvent?.Invoke(false); }; _mainRoomCreationViewController = BeatSaberUI.CreateViewController <MainRoomCreationViewController>(); _mainRoomCreationViewController.CreatedRoom += CreateRoomPressed; _mainRoomCreationViewController.SavePresetPressed += SavePreset; _mainRoomCreationViewController.LoadPresetPressed += LoadPresetPressed; _mainRoomCreationViewController.keyboardDidFinishEvent += _mainRoomCreationViewController_keyboardDidFinishEvent; _mainRoomCreationViewController.didFinishEvent += () => { DismissViewController(_mainRoomCreationViewController); SetLeftScreenViewController(null); }; _presetsListViewController = BeatSaberUI.CreateViewController <PresetsListViewController>(); _presetsListViewController.didFinishEvent += _presetsListViewController_didFinishEvent; } ProvideInitialViewControllers(_serverHubsViewController, null, null); }
public static void UpdateLevelVariables(LevelCollectionSO collection) { if (collection != null && collection.levels != null) { int total_levels = collection.levels.Count; for (int i = 0; i < total_levels ; i++) { LevelData levelData = collection.levels[i].levelData; int index = LEVELS.FindIndex(x => x.id == levelData.id); LocalLevelData data = null; if (index < 0) { data = new LocalLevelData(); LEVELS.Add(data); } else { data = LEVELS[index]; } data.id = levelData.id; data.sceneName = levelData.sceneName; data.maxLives = levelData.maxLives; data.difficulty = levelData.difficulty; } Debug.Log("Level Data Variable Updated"); } else { Debug.LogError("Level collection SO is null"); } }
protected override void DidActivate(bool firstActivation, ActivationType activationType) { _beatmapCharacteristics = Resources.FindObjectsOfTypeAll <BeatmapCharacteristicSO>(); _standardCharacteristic = _beatmapCharacteristics.First(x => x.characteristicName == "Standard"); _levelCollection = SongLoader.CustomLevelCollectionSO; if (firstActivation && activationType == ActivationType.AddedToHierarchy) { _lastCharacteristic = _standardCharacteristic; _roomManagementViewController = BeatSaberUI.CreateViewController <RoomManagementViewController>(); _roomManagementViewController.DestroyRoomPressed += DestroyRoomPressed; _roomNavigationController = BeatSaberUI.CreateViewController <RoomNavigationController>(); _roomNavigationController.didFinishEvent += () => { LeaveRoom(); }; _searchKeyboard = BeatSaberUI.CreateViewController <CustomKeyboardViewController>(); _searchKeyboard.enterButtonPressed += SearchPressed; _searchKeyboard.backButtonPressed += () => { DismissViewController(_searchKeyboard); }; _searchKeyboard.allowEmptyInput = true; } ProvideInitialViewControllers(_roomNavigationController, _roomManagementViewController, null); }
private void SetupTweaks() { if (initialized || PluginConfig.disableSongListTweaks) { return; } Logger.Log("Setting up song list tweaks..."); _playlistsFlowCoordinator = (new GameObject("PlaylistsFlowCoordinator")).AddComponent <PlaylistsFlowCoordinator>(); _playlistsFlowCoordinator.didFinishEvent += _playlistsFlowCoordinator_didFinishEvent; _beatmapCharacteristics = Resources.FindObjectsOfTypeAll <BeatmapCharacteristicSO>(); _lastCharacteristic = _beatmapCharacteristics.First(x => x.characteristicName == "Standard"); Resources.FindObjectsOfTypeAll <BeatmapCharacteristicSelectionViewController>().First().didSelectBeatmapCharacteristicEvent += (BeatmapCharacteristicSelectionViewController sender, BeatmapCharacteristicSO selected) => { _lastCharacteristic = selected; }; if (SongLoader.AreSongsLoaded) { _levelCollection = SongLoader.CustomLevelCollectionSO; } else { SongLoader.SongsLoadedEvent += (SongLoader sender, List <CustomLevel> levels) => { _levelCollection = SongLoader.CustomLevelCollectionSO; }; } _mainFlowCoordinator = Resources.FindObjectsOfTypeAll <MainFlowCoordinator>().FirstOrDefault(); _mainFlowCoordinator.GetPrivateField <MainMenuViewController>("_mainMenuViewController").didFinishEvent += SongListTweaks_didFinishEvent; _simpleDialog = ReflectionUtil.GetPrivateField <SimpleDialogPromptViewController>(_mainFlowCoordinator, "_simpleDialogPromptViewController"); _simpleDialog = Instantiate(_simpleDialog.gameObject, _simpleDialog.transform.parent).GetComponent <SimpleDialogPromptViewController>(); _difficultyViewController = Resources.FindObjectsOfTypeAll <BeatmapDifficultyViewController>().FirstOrDefault(); _difficultyViewController.didSelectDifficultyEvent += _difficultyViewController_didSelectDifficultyEvent; _levelListViewController = Resources.FindObjectsOfTypeAll <LevelListViewController>().FirstOrDefault(); _levelListViewController.didSelectLevelEvent += _levelListViewController_didSelectLevelEvent;; RectTransform _tableViewRectTransform = _levelListViewController.GetComponentsInChildren <RectTransform>().First(x => x.name == "TableViewContainer"); _tableViewRectTransform.sizeDelta = new Vector2(0f, -20f); _tableViewRectTransform.anchoredPosition = new Vector2(0f, -2.5f); RectTransform _pageUp = _tableViewRectTransform.GetComponentsInChildren <RectTransform>(true).First(x => x.name == "PageUpButton"); _pageUp.anchoredPosition = new Vector2(0f, -1f); RectTransform _pageDown = _tableViewRectTransform.GetComponentsInChildren <RectTransform>(true).First(x => x.name == "PageDownButton"); _pageDown.anchoredPosition = new Vector2(0f, 1f); _searchButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(-20f, 36.25f), new Vector2(20f, 6f), SearchPressed, "Search"); _searchButton.SetButtonTextSize(3f); _searchButton.ToggleWordWrapping(false); _sortByButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(0f, 36.25f), new Vector2(20f, 6f), () => { SelectTopButtons(TopButtonsState.SortBy); }, "Sort By"); _sortByButton.SetButtonTextSize(3f); _sortByButton.ToggleWordWrapping(false); _playlistsButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(20f, 36.25f), new Vector2(20f, 6f), PlaylistsButtonPressed, "Playlists"); _playlistsButton.SetButtonTextSize(3f); _playlistsButton.ToggleWordWrapping(false); _defButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(-20f, 36.25f), new Vector2(20f, 6f), () => { SelectTopButtons(TopButtonsState.Select); SetLevels(_lastCharacteristic, SortMode.Default, ""); }, "Default"); _defButton.SetButtonTextSize(3f); _defButton.ToggleWordWrapping(false); _defButton.gameObject.SetActive(false); _newButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(0f, 36.25f), new Vector2(20f, 6f), () => { SelectTopButtons(TopButtonsState.Select); SetLevels(_lastCharacteristic, SortMode.Newest, ""); }, "Newest"); _newButton.SetButtonTextSize(3f); _newButton.ToggleWordWrapping(false); _newButton.gameObject.SetActive(false); _authorButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(20f, 36.25f), new Vector2(20f, 6f), () => { SelectTopButtons(TopButtonsState.Select); SetLevels(_lastCharacteristic, SortMode.Difficulty, ""); }, "Difficulty"); _authorButton.SetButtonTextSize(3f); _authorButton.ToggleWordWrapping(false); _authorButton.gameObject.SetActive(false); _detailViewController = Resources.FindObjectsOfTypeAll <StandardLevelDetailViewController>().First(x => x.name == "StandardLevelDetailViewController"); RectTransform buttonsRect = _detailViewController.GetComponentsInChildren <RectTransform>().First(x => x.name == "Buttons"); buttonsRect.anchoredPosition = new Vector2(0f, 10.75f); RectTransform customButtonsRect = Instantiate(buttonsRect, buttonsRect.parent, true); Destroy(customButtonsRect.GetComponent <ContentSizeFitter>()); Destroy(customButtonsRect.GetComponent <HorizontalLayoutGroup>()); customButtonsRect.name = "CustomUIButtonsHolder"; customButtonsRect.anchoredPosition = new Vector2(0f, 1.25f); _favoriteButton = customButtonsRect.GetComponentsInChildren <Button>().First(x => x.name == "PracticeButton"); _favoriteButton.SetButtonIcon(Base64Sprites.AddToFavorites); _favoriteButton.onClick.AddListener(() => { if (PluginConfig.favoriteSongs.Any(x => x.Contains(_detailViewController.difficultyBeatmap.level.levelID))) { PluginConfig.favoriteSongs.Remove(_detailViewController.difficultyBeatmap.level.levelID); PluginConfig.SaveConfig(); _favoriteButton.SetButtonIcon(Base64Sprites.AddToFavorites); PlaylistsCollection.RemoveLevelFromPlaylist(PlaylistsCollection.loadedPlaylists.First(x => x.playlistTitle == "Your favorite songs"), _detailViewController.difficultyBeatmap.level.levelID); } else { PluginConfig.favoriteSongs.Add(_detailViewController.difficultyBeatmap.level.levelID); PluginConfig.SaveConfig(); _favoriteButton.SetButtonIcon(Base64Sprites.RemoveFromFavorites); PlaylistsCollection.AddSongToPlaylist(PlaylistsCollection.loadedPlaylists.First(x => x.playlistTitle == "Your favorite songs"), new PlaylistSong() { levelId = _detailViewController.difficultyBeatmap.level.levelID, songName = _detailViewController.difficultyBeatmap.level.songName, level = SongDownloader.GetLevel(_detailViewController.difficultyBeatmap.level.levelID) }); } }); _deleteButton = customButtonsRect.GetComponentsInChildren <Button>().First(x => x.name == "PlayButton"); _deleteButton.SetButtonText("Delete"); _deleteButton.ToggleWordWrapping(false); _deleteButton.onClick.AddListener(DeletePressed); _deleteButton.GetComponentsInChildren <RectTransform>().First(x => x.name == "GlowContainer").gameObject.SetActive(false); _deleteButton.interactable = !PluginConfig.disableDeleteButton; //based on https://github.com/halsafar/BeatSaberSongBrowser/blob/master/SongBrowserPlugin/UI/Browser/SongBrowserUI.cs#L192 var statsPanel = _detailViewController.GetComponentsInChildren <CanvasRenderer>(true).First(x => x.name == "LevelParamsPanel"); var statTransforms = statsPanel.GetComponentsInChildren <RectTransform>(); var valueTexts = statsPanel.GetComponentsInChildren <TextMeshProUGUI>().Where(x => x.name == "ValueText").ToList(); foreach (RectTransform r in statTransforms) { if (r.name == "Separator") { continue; } r.sizeDelta = new Vector2(r.sizeDelta.x * 0.85f, r.sizeDelta.y * 0.85f); } var _starStatTransform = Instantiate(statTransforms[1], statsPanel.transform, false); _starStatText = _starStatTransform.GetComponentInChildren <TextMeshProUGUI>(); _starStatTransform.GetComponentInChildren <UnityEngine.UI.Image>().sprite = Base64Sprites.StarFull; _starStatText.text = "--"; initialized = true; }
void SelectAndLoadSong(string name, string difficulty) { //try //{ // mainMenuViewController.HandleMenuButton(MainMenuViewController.MenuButton.SoloFreePlay); //} //catch (Exception e) //{ //} //try //{ // soloModeSelectionViewController.HandleMenuButton(SoloModeSelectionViewController.MenuType.FreePlayMode); //} //catch (Exception e) //{ //} LevelCollectionSO _levelCollection = SongLoader.CustomLevelCollectionSO; LevelSO level = _levelCollection.GetLevelsWithBeatmapCharacteristic(Resources.FindObjectsOfTypeAll <BeatmapCharacteristicSO>().First(x => x.characteristicName == "Standard")).First(x => x.songName == name); //level = listViewController.GetPrivateField<IBeatmapLevel[]>("_levels").Where(x => x.songName == name)// && x.songAuthorName == author && x.songSubName == subname) // .ToList().ElementAt(0); Console.WriteLine("Song found:" + level.songName); difficultyLevel = level.GetDifficultyBeatmap(_difficulties[difficulty]); ////////////////////////////////////////////////////////////////// // THING TO GET SONG BY JUST STARTING IT // ////////////////////////////////////////////////////////////////// GameplayModifiers gameplayModifiers = new GameplayModifiers(); gameplayModifiers.ResetToDefault(); gameplayModifiers.noFail = true; PlayerSpecificSettings playerSettings = Resources.FindObjectsOfTypeAll <PlayerDataModelSO>().FirstOrDefault().currentLocalPlayer.playerSpecificSettings; var practiceSettings = new PracticeSettings(PracticeSettings.defaultPracticeSettings); practiceSettings.startSongTime = time; practiceSettings.songSpeedMul = playbackSpeed; MenuSceneSetupDataSO menu = Resources.FindObjectsOfTypeAll <MenuSceneSetupDataSO>().First(); SongLoader loader = Resources.FindObjectsOfTypeAll <SongLoader>().First(); loader.LoadAudioClipForLevel((CustomLevel)level, delegate(CustomLevel customLevel) { menu.StartStandardLevel(difficultyLevel, gameplayModifiers, playerSettings, practiceSettings, null, null); }); /////////////////////////////////////////////////////////////////// // THING TO GET SONG BY NAVIGATING THROUGH MENUS // /////////////////////////////////////////////////////////////////// //MenuSceneSetupDataSO menu = Resources.FindObjectsOfTypeAll<MenuSceneSetupDataSO>().First(); //soloFreePlayFlowCoordinator.HandleLevelListViewControllerDidSelectLevel(listViewController, level); //levelListView.SelectAndScrollToLevel(level.levelID); //int row = levelListView.RowNumberForLevelID(level.levelID); //levelListView.HandleDidSelectRowEvent(levelListView.GetPrivateField<TableView>("_tableView"), row); //try //{ // DifficultyTableView difficultyTableView = beatmapDifficultyViewController.GetPrivateField<DifficultyTableView>("_difficultyTableView"); // TableView tableView = difficultyTableView.GetPrivateField<TableView>("_tableView"); // difficultyTableView.HandleDidSelectRowEvent(tableView, 0); // tableView.SelectRow(0); // difficultyTableView.SelectRow(difficultyLevel, false); // soloFreePlayFlowCoordinator.HandleDifficultyViewControllerDidSelectDifficulty(beatmapDifficultyViewController, difficultyLevel); // practiceController.Init(level, new PracticeSettings()); // GameplayModifiers gameplayModifiers = new GameplayModifiers(); // gameplayModifiers.ResetToDefault(); // gameplayModifiers.noFail = true; // gameplaySetupViewController.SetData(gameplaySetupViewController.playerSettings, gameplayModifiers); // soloFreePlayFlowCoordinator.HandleLevelDetailViewControllerDidPressPracticeButton(detailViewController); // Console.WriteLine("loading " + difficultyLevel.level.songName); // detailViewController.PracticeButtonPressed(); // if (!autoPlayBuffer && time > 2) // { // pause on start // practiceController.HandleSongStartScrollbarOnValueChanged(time - 2); // } // else // { // autoplay or negative time will f**k it up // practiceController.HandleSongStartScrollbarOnValueChanged(time); // } // Console.WriteLine("Starting song at: " + practiceController.GetPrivateField<PracticeSettings>("_practiceSettings").startSongTime); // practiceController.PlayButtonPressed(); // soloFreePlayFlowCoordinator.HandlePracticeViewControllerDidPressPlayButton(); //} //catch (Exception e) //{ // Console.WriteLine(e); // //Console.WriteLine(e.StackTrace); //} //finally //{ // Console.WriteLine("[Mediocre Loader] Finally"); //} //mainGameSceneSetupData.TransitionToScene(0.7f); }
/// <summary> /// Get the song cache from the game. /// </summary> public void UpdateSongLists(BeatmapCharacteristicSO gameplayMode) { // give up if (gameplayMode == null) { Logger.Debug("Always null first time if user waits for SongLoader event, which they should..."); return; } Stopwatch timer = new Stopwatch(); timer.Start(); // Get the level collection from song loader LevelCollectionSO levelCollections = Resources.FindObjectsOfTypeAll <LevelCollectionSO>().FirstOrDefault(); // Stash everything we need _originalSongs = levelCollections.GetLevelsWithBeatmapCharacteristic(gameplayMode).ToList(); Logger.Debug("Got {0} songs from level collections...", _originalSongs.Count); //_originalSongs.ForEach(x => Logger.Debug("{0} by {1} = {2}", x.name, x.levelAuthorName, x.levelID)); _sortedSongs = _originalSongs; CurrentBeatmapCharacteristicSO = gameplayMode; // Calculate some information about the custom song dir String customSongsPath = Path.Combine(Environment.CurrentDirectory, CUSTOM_SONGS_DIR); String revSlashCustomSongPath = customSongsPath.Replace('\\', '/'); double currentCustomSongDirLastWriteTIme = (File.GetLastWriteTimeUtc(customSongsPath) - EPOCH).TotalMilliseconds; bool customSongDirChanged = false; if (_customSongDirLastWriteTime != currentCustomSongDirLastWriteTIme) { customSongDirChanged = true; _customSongDirLastWriteTime = currentCustomSongDirLastWriteTIme; } // This operation scales well if (!Directory.Exists(customSongsPath)) { Logger.Error("CustomSong directory is missing..."); return; } IEnumerable <string> directories = Directory.EnumerateDirectories(customSongsPath, "*.*", SearchOption.AllDirectories); // Get LastWriteTimes Stopwatch lastWriteTimer = new Stopwatch(); lastWriteTimer.Start(); foreach (var level in SongLoader.CustomLevels) { // If we already know this levelID, don't both updating it. // SongLoader should filter duplicates but in case of failure we don't want to crash if (!_cachedLastWriteTimes.ContainsKey(level.levelID) || customSongDirChanged) { _cachedLastWriteTimes[level.levelID] = (File.GetLastWriteTimeUtc(level.customSongInfo.path) - EPOCH).TotalMilliseconds; } if (!_levelIdToCustomLevel.ContainsKey(level.levelID)) { _levelIdToCustomLevel.Add(level.levelID, level); } if (!_levelIdToSongVersion.ContainsKey(level.levelID)) { DirectoryInfo info = new DirectoryInfo(level.customSongInfo.path); string currentDirectoryName = info.Name; String version = level.customSongInfo.path.Replace(revSlashCustomSongPath, "").Replace(currentDirectoryName, "").Replace("/", ""); if (!String.IsNullOrEmpty(version)) { //Logger.Debug("MATCH"); _levelIdToSongVersion.Add(level.levelID, version); _keyToSong.Add(version, level); } } } lastWriteTimer.Stop(); Logger.Info("Determining song download time and determining mappings took {0}ms", lastWriteTimer.ElapsedMilliseconds); // Update song Infos, directory tree, and sort this.UpdateScoreSaberDataMapping(); this.UpdatePlayCounts(); this.UpdateDirectoryTree(customSongsPath); // Check if we need to upgrade settings file favorites try { this.Settings.ConvertFavoritesToPlaylist(_levelIdToCustomLevel, _levelIdToSongVersion); } catch (Exception e) { Logger.Exception("FAILED TO CONVERT FAVORITES TO PLAYLIST!", e); } // load the current editing playlist or make one if (!String.IsNullOrEmpty(this.Settings.currentEditingPlaylistFile)) { CurrentEditingPlaylist = PlaylistsReader.ParsePlaylist(this.Settings.currentEditingPlaylistFile); } if (CurrentEditingPlaylist == null) { CurrentEditingPlaylist = new Playlist { Title = "Song Browser Favorites", Author = "SongBrowserPlugin", Path = this.Settings.currentEditingPlaylistFile, Image = Base64Sprites.PlaylistIconB64, Songs = new List <PlaylistSong>(), }; } CurrentEditingPlaylistLevelIds = new HashSet <string>(); foreach (PlaylistSong ps in CurrentEditingPlaylist.Songs) { CurrentEditingPlaylistLevelIds.Add(ps.LevelId); } // Actually sort and filter this.ProcessSongList(); // Signal complete if (SongLoader.CustomLevels.Count > 0) { didFinishProcessingSongs?.Invoke(SongLoader.CustomLevels); } timer.Stop(); Logger.Info("Updating songs infos took {0}ms", timer.ElapsedMilliseconds); Logger.Debug("Song Browser knows about {0} songs from SongLoader...", _originalSongs.Count); }