Ejemplo n.º 1
0
        private void OnModeSelection(FreePlayMode mode)
        {
            if (mode == FreePlayMode.Solo)
            {
                Logger.log.Debug("Selected solo free play mode");
                _freePlayFlowCoordinator = FindObjectOfType <SoloFreePlayFlowCoordinator>();
                (_freePlayFlowCoordinator as SoloFreePlayFlowCoordinator).didFinishEvent += OnFreePlayFlowCoordinatorFinished;

                PrepareLevelPackSelectedEvent();
                if (!SongBrowserTweaks.ModLoaded)
                {
                    UnityCoroutineHelper.StartDelayedAction(SelectSavedLevelPack);
                }
                else if (!SongBrowserTweaks.Initialized)
                {
                    StartCoroutine(GetSongBrowserButtons());
                }
            }
            else if (mode == FreePlayMode.Party)
            {
                Logger.log.Debug("Selected party free play mode");
                _freePlayFlowCoordinator = FindObjectOfType <PartyFreePlayFlowCoordinator>();
                (_freePlayFlowCoordinator as PartyFreePlayFlowCoordinator).didFinishEvent += OnFreePlayFlowCoordinatorFinished;

                PrepareLevelPackSelectedEvent();
                if (!SongBrowserTweaks.ModLoaded)
                {
                    UnityCoroutineHelper.StartDelayedAction(SelectSavedLevelPack);
                }
                else if (!SongBrowserTweaks.Initialized)
                {
                    StartCoroutine(GetSongBrowserButtons());
                }
            }
            else if (mode == FreePlayMode.Campaign)
            {
                Logger.log.Debug("Selected campaign play mode");
                _freePlayFlowCoordinator = FindObjectOfType <CampaignFlowCoordinator>();
                (_freePlayFlowCoordinator as CampaignFlowCoordinator).didFinishEvent += OnFreePlayFlowCoordinatorFinished;
            }

            // UIState in SongBrowser is always reset to Main, so we need to disable the filter button
            SongBrowserTweaks.DisableOtherFiltersButton();
        }
        public void HideScreen(bool immediately = false)
        {
            if (!_floatingScreen.gameObject.activeSelf)
            {
                return;
            }

            if (immediately)
            {
                _floatingScreen.transform.localScale = new Vector3(HiddenScale, HiddenScale, _floatingScreen.transform.localScale.z);
                (_floatingScreen.transform as RectTransform).sizeDelta = new Vector2(DefaultXSize, DefaultYSize);

                _floatingScreen.gameObject.SetActive(false);
            }
            else
            {
                _revealAnimation = UnityCoroutineHelper.Start(RevealAnimationCoroutine(HiddenScale, true));
            }
        }
Ejemplo n.º 3
0
        public static void OnHandleUnresolvedException(object sender, UnhandledExceptionEventArgs args)
        {
            if (args == null || args.ExceptionObject == null)
            {
                return;
            }
            var exception = args.ExceptionObject as Exception;

            if (exception != null)
            {
                Debug.Log("Unhandled exception: " + exception.ToString());
#if UNITY_IOS && !UNITY_EDITOR
                TrackErrorWithAttachments(exception);
#else
                lock (_unhandledExceptions)
                {
                    _unhandledExceptions.Enqueue(exception);
                }
                UnityCoroutineHelper.StartCoroutine(SendUnhandledExceptionReports);
#endif
            }
        }
Ejemplo n.º 4
0
        public static void OnHandleUnresolvedException(object sender, UnhandledExceptionEventArgs args)
        {
            if (args == null || args.ExceptionObject == null)
            {
                return;
            }
            var exception = args.ExceptionObject as Exception;

            if (exception != null)
            {
                Debug.Log("Unhandled exception: " + exception.ToString());
#if UNITY_ANDROID
                lock (_unhandledExceptions)
                {
                    _unhandledExceptions.Enqueue(exception);
                }
                UnityCoroutineHelper.StartCoroutine(SendUnhandledExceptionReports);
#else
                var exceptionWrapper = CreateWrapperException(exception);
                CrashesInternal.TrackException(exceptionWrapper.GetRawObject());
#endif
            }
        }
        public void ShowScreen(bool immediately = false)
        {
            if (_floatingScreen.gameObject.activeSelf)
            {
                return;
            }

            if (immediately)
            {
                _floatingScreen.transform.localScale = new Vector3(DefaultScale, DefaultScale, _floatingScreen.transform.localScale.z);
                (_floatingScreen.transform as RectTransform).sizeDelta = new Vector2(DefaultXSize, DefaultYSize);

                _outlineImage.color = OutlineColour;
                _iconImage.color    = Color.white;
                _text.color         = Color.white;

                _floatingScreen.gameObject.SetActive(true);
            }
            else
            {
                _floatingScreen.gameObject.SetActive(true);
                _revealAnimation = UnityCoroutineHelper.Start(RevealAnimationCoroutine(DefaultScale));
            }
        }
Ejemplo n.º 6
0
        private void LevelPackSelected(LevelFilteringNavigationController navController, IAnnotatedBeatmapLevelCollection levelPack, GameObject noDataInfoPrefab, BeatmapCharacteristicSO preferredCharacteristic)
        {
            // ignore the first select event that's fired immediately after the user select the free play mode
            // this is done so we can select the saved last pack later
            // when the saved pack is selected, it will then call this function again for sorting/storing
            if (_isSelectingInitialLevelPack)
            {
                _lastPack = levelPack;
                _isSelectingInitialLevelPack = false;

                if (levelPack is IBeatmapLevelPack beatmapLevelPack)
                {
                    Logger.log.Debug($"Storing '{beatmapLevelPack.packName}' (id = '{beatmapLevelPack.packID}') level pack as initial pack");
                }
                else
                {
                    Logger.log.Debug($"Storing '{levelPack.collectionName}' level collection as initial pack");
                }

                return;
            }
            // in ConfirmDeleteButtonClicked, the call to SongCore.Loader.Instance.DeleteSong will reload the level packs
            // which causes the custom level pack to be re-selected. but, if filters are applied or level pack is sorted,
            // we want to reshow our own filtered/sorted level pack and not reset our UI, so we don't have to handle this event
            // this code is kinda smelly tbh, but can't do anything about it unless there are changes to SongCore
            else if (_isDeletingSongInModOwnedLevelPack)
            {
                return;
            }
            // when SongBrowser is enabled, we only need to store the pack for the WordPredictionEngine when using the search feature
            else if (SongBrowserTweaks.Initialized)
            {
                _lastPack = levelPack;
                SongBrowserTweaks.DisableOtherFiltersButton();
                return;
            }

            if (levelPack.collectionName != FilteredLevelsLevelPack.CollectionName)
            {
                _lastPack = levelPack;

                // store level pack to PluginConfig
                var tabBarVC    = LevelFilteringNavigationController.GetPrivateField <TabBarViewController>("_tabBarViewController");
                var tabBarItems = tabBarVC.GetPrivateField <TabBarViewController.TabBarItem[]>("_items");

                string lastLevelPackString = tabBarItems[tabBarVC.selectedCellNumber].title + PluginConfig.LastLevelPackIDSeparator;
                if (levelPack is IBeatmapLevelPack beatmapLevelPack)
                {
                    lastLevelPackString += beatmapLevelPack.packID;
                    Logger.log.Debug($"Storing '{beatmapLevelPack.packName}' (id = '{beatmapLevelPack.packID}') level pack as last pack");
                }
                else
                {
                    lastLevelPackString += levelPack.collectionName;
                    Logger.log.Debug($"Storing '{levelPack.collectionName}' level collection as last pack");
                }
                PluginConfig.LastLevelPackID = lastLevelPackString;

                // reapply sort mode
                if (!SongSortModule.IsDefaultSort)
                {
                    _sortedLevelsLevelPack.SetupFromLevelCollection(levelPack);

                    // since the level selection navigation controller shows a level pack using the same event that calls this function
                    // and it technically isn't a guarantee that this function will run after it is set,
                    // delay setting our level pack
                    UnityCoroutineHelper.StartDelayedAction(() =>
                                                            LevelSelectionNavigationController.SetData(
                                                                _sortedLevelsLevelPack,
                                                                true,
                                                                LevelSelectionNavigationController.GetPrivateField <bool>("_showPlayerStatsInDetailView"),
                                                                LevelSelectionNavigationController.GetPrivateField <bool>("_showPracticeButtonInDetailView")));
                }
            }

            // SongBrowser can now apply filters to OST levels and switch between different level packs
            // so our old behaviour of cancelling the filters is no longer needed
            // that being said, without SongBrowser, we are still going to cancel filters upon switching level packs
            // because i'd rather the player have to go into the FilterViewController,
            // so that it can check if all the beatmap details have been loaded
            if (FilterList.AnyApplied)
            {
                Logger.log.Debug("Another level pack has been selected, unapplying filters");
            }
            UnapplyFilters();

            if (_uiAdditions != null)
            {
                UnityCoroutineHelper.StartDelayedAction(_uiAdditions.RefreshPageButtons);
            }
        }
Ejemplo n.º 7
0
        private void SelectSavedLevelPack()
        {
            string lastLevelPackString = PluginConfig.LastLevelPackID;
            int    separatorPos        = lastLevelPackString.IndexOf(PluginConfig.LastLevelPackIDSeparator);

            if (separatorPos < 0 || separatorPos + PluginConfig.LastLevelPackIDSeparator.Length >= lastLevelPackString.Length)
            {
                goto OnError;
            }

            string lastLevelPackCollectionTitle = lastLevelPackString.Substring(0, separatorPos);
            string lastLevelPackID = lastLevelPackString.Substring(separatorPos + PluginConfig.LastLevelPackIDSeparator.Length);

            TabBarViewController tabBarVC = LevelFilteringNavigationController.GetPrivateField <TabBarViewController>("_tabBarViewController");

            TabBarViewController.TabBarItem[] tabBarItems = tabBarVC.GetPrivateField <TabBarViewController.TabBarItem[]>("_items");
            if (tabBarItems == null)
            {
                goto OnError;
            }

            var item = tabBarItems.FirstOrDefault(x => x.title == lastLevelPackCollectionTitle);

            if (item == null)
            {
                goto OnError;
            }

            int itemIndex = Array.IndexOf(tabBarItems, item);

            if (itemIndex < 0)
            {
                goto OnError;
            }

            var tabBarDatas = LevelFilteringNavigationController.GetPrivateField <object[]>("_tabBarDatas");

            if (itemIndex >= tabBarDatas.Length)
            {
                goto OnError;
            }

            var levelPacks = tabBarDatas[itemIndex].GetField <IAnnotatedBeatmapLevelCollection[]>("annotatedBeatmapLevelCollections");

            if (levelPacks == null)
            {
                goto OnError;
            }

            IAnnotatedBeatmapLevelCollection levelPack = levelPacks.FirstOrDefault(x => x.collectionName == lastLevelPackID || (x is IBeatmapLevelPack && ((IBeatmapLevelPack)x).packID == lastLevelPackID));

            if (levelPack == null)
            {
                goto OnError;
            }

            // this should trigger the LevelPackSelected() delegate and sort the level pack as well
            LevelFilteringNavigationController.SelectAnnotatedBeatmapLevelCollection(levelPack);

            // try to select last level as well
            string[] lastLevelData = PluginConfig.LastLevelID.Split(new string[] { PluginConfig.LastLevelIDSeparator }, StringSplitOptions.None);
            if (lastLevelData.Length != 3)
            {
                return;
            }

            // select last level on the next frame, since the sort mode reselection done in LevelPackSelected
            // will be delayed to the next frame and will cause the level to be deselected
            UnityCoroutineHelper.StartDelayedAction(delegate()
            {
                string levelID = lastLevelData[0];

                if (levelPack.beatmapLevelCollection?.beatmapLevels == null)
                {
                    return;
                }

                IPreviewBeatmapLevel level = levelPack.beatmapLevelCollection.beatmapLevels.FirstOrDefault(x => x.levelID == levelID);
                if (level != null)
                {
                    SelectLevel(level);
                }
                else
                {
                    // could not find level with levelID
                    // either song was deleted or is a WIP level and was changed
                    // try using song name and level author as fallback
                    string songName    = lastLevelData[1];
                    string levelAuthor = lastLevelData[2];

                    level = levelPack.beatmapLevelCollection.beatmapLevels.FirstOrDefault(x => x.songName == songName && x.levelAuthorName == levelAuthor);
                    if (level != null)
                    {
                        SelectLevel(level);
                    }
                }
            }, 2, false);

            return;

OnError:
            SongSortModule.ResetSortMode();
            if (ButtonPanel.IsSingletonAvailable)
            {
                ButtonPanel.instance.UpdateSortButtons();
            }
        }
        public BottomScreen()
        {
            _floatingScreen = FloatingScreen.CreateFloatingScreen(new Vector2(DefaultXSize, DefaultYSize), false, new Vector3(1.5f, 0.05f, 1.5f), Quaternion.Euler(50f, 0f, 0f));
            (_floatingScreen.transform as RectTransform).pivot = new Vector2(1f, 0f);

            // this is needed to fix HoverHint position issues that occur because of the change in pivot done to the floating screen
            var wrapperCanvasGO = new GameObject("Wrapper", typeof(RectTransform), typeof(Canvas), typeof(VRGraphicRaycaster), typeof(SetMainCameraToCanvas));
            var rt = wrapperCanvasGO.transform as RectTransform;

            rt.SetParent(_floatingScreen.transform, false);
            rt.anchorMin = Vector2.zero;
            rt.anchorMax = Vector2.one;
            rt.sizeDelta = Vector2.zero;

            var cameraSetter = wrapperCanvasGO.GetComponent <SetMainCameraToCanvas>();

            cameraSetter.SetField("_canvas", wrapperCanvasGO.GetComponent <Canvas>());
            cameraSetter.SetField("_mainCamera", Resources.FindObjectsOfTypeAll <MainCamera>().FirstOrDefault(camera => camera.camera?.stereoTargetEye != StereoTargetEyeMask.None) ?? Resources.FindObjectsOfTypeAll <MainCamera>().FirstOrDefault());

            _outlineImage                = new GameObject("Outline").AddComponent <Image>();
            _outlineImage.color          = OutlineColour;
            _outlineImage.material       = UIUtilities.NoGlowMaterial;
            _outlineImage.type           = Image.Type.Sliced;
            _outlineImage.sprite         = Resources.FindObjectsOfTypeAll <Sprite>().LastOrDefault(x => x.name == "RoundRectSmallStroke");
            _outlineImage.preserveAspect = true;

            _outlineImage.rectTransform.SetParent(wrapperCanvasGO.transform, false);
            _outlineImage.rectTransform.anchorMin = Vector2.zero;
            _outlineImage.rectTransform.anchorMax = Vector2.one;
            _outlineImage.rectTransform.sizeDelta = Vector2.zero;

            var hlg = new GameObject("HorizontalLayoutGroup").AddComponent <HorizontalLayoutGroup>();

            hlg.spacing                = 3.5f;
            hlg.padding                = new RectOffset(2, 2, 1, 1);
            hlg.childAlignment         = TextAnchor.MiddleCenter;
            hlg.childForceExpandWidth  = false;
            hlg.childForceExpandHeight = false;

            rt = hlg.transform as RectTransform;
            rt.SetParent(wrapperCanvasGO.transform, false);
            rt.anchorMin = new Vector2(1f, 0f);
            rt.anchorMax = new Vector2(1f, 0f);
            rt.pivot     = new Vector2(1f, 0f);
            rt.sizeDelta = new Vector2(DefaultXSize, DefaultYSize);

            // icon
            _iconImage                = new GameObject("Icon").AddComponent <Image>();
            _iconImage.material       = UIUtilities.NoGlowMaterial;
            _iconImage.sprite         = BSUIUtilities.LoadSpriteFromResources("EnhancedSearchAndFilters.Assets.bars.png");
            _iconImage.preserveAspect = true;

            var le = _iconImage.gameObject.AddComponent <LayoutElement>();

            le.preferredWidth  = 4.5f;
            le.preferredHeight = 4.5f;

            _iconImage.rectTransform.SetParent(rt, false);

            // text
            _text           = BeatSaberUI.CreateText(rt, "OPTIONS", Vector2.zero, Vector2.zero);
            _text.fontSize  = 4.4f;
            _text.alignment = TextAlignmentOptions.Center;

            // this needs to be the last child, otherwise the outline image will capture all the controller raycasts first
            UIUtilities.ParseBSML("EnhancedSearchAndFilters.UI.Views.BottomScreen.BottomScreenView.bsml", wrapperCanvasGO, this);

            _hoverEventHandler = _floatingScreen.gameObject.AddComponent <EnterExitEventHandler>();
            _hoverEventHandler.PointerEntered += delegate()
            {
                if (_revealAnimation != null)
                {
                    return;
                }
                else if (_contractAnimation != null)
                {
                    UnityCoroutineHelper.Stop(_contractAnimation);
                    _contractAnimation = null;
                }

                _expandAnimation = UnityCoroutineHelper.Start(ExpandAnimationCoroutine());
            };
            _hoverEventHandler.PointerExited += delegate()
            {
                if (_revealAnimation != null)
                {
                    return;
                }

                bool immediate = false;
                if (_expandAnimation != null)
                {
                    UnityCoroutineHelper.Stop(_expandAnimation);
                    _expandAnimation = null;
                    immediate        = true;
                }
                else if (_contractAnimation != null)
                {
                    UnityCoroutineHelper.Stop(_contractAnimation);
                    _contractAnimation = null;
                }

                _contractAnimation = UnityCoroutineHelper.Start(ContractAnimationCoroutine(immediate));
            };

            var sortModeTab = new SortModeTab(_container);

            sortModeTab.SortButtonPressed += () => SortButtonPressed?.Invoke();
            sortModeTab.Visible            = true;

            _currentTab = sortModeTab;
            _tabs[0]    = sortModeTab;
            Logger.log.Notice($"finished constructor, currentTab?={_currentTab == null}");

            HideScreen(true);
        }