Example #1
0
 public LTUI(Config config, StandardLevelDetailViewController standardLevelDetailViewController)
 {
     Y2Pos   = -100f;
     _config = config;
     _standardLevelDetailViewController = standardLevelDetailViewController;
     _detailView = standardLevelDetailViewController.GetField <StandardLevelDetailView, StandardLevelDetailViewController>("_standardLevelDetailView");
 }
Example #2
0
        /// <summary>
        /// Constructor.  Acquire all necessary BeatSaberUi elements.
        /// </summary>
        /// <param name="flowCoordinator"></param>
        public BeatSaberUIController(LevelSelectionFlowCoordinator flowCoordinator)
        {
            Logger.Debug("Collecting all BeatSaberUI Elements...");

            LevelSelectionFlowCoordinator = flowCoordinator;

            // gather flow coordinator elements
            LevelSelectionNavigationController = LevelSelectionFlowCoordinator.GetField <LevelSelectionNavigationController, LevelSelectionFlowCoordinator>("levelSelectionNavigationController");
            Logger.Debug("Acquired LevelSelectionNavigationController [{0}]", LevelSelectionNavigationController.GetInstanceID());

            LevelFilteringNavigationController = LevelSelectionNavigationController.GetField <LevelFilteringNavigationController, LevelSelectionNavigationController>("_levelFilteringNavigationController");
            Logger.Debug("Acquired LevelFilteringNavigationController [{0}]", LevelFilteringNavigationController.GetInstanceID());

            LevelCollectionNavigationController = LevelSelectionNavigationController.GetField <LevelCollectionNavigationController, LevelSelectionNavigationController>("_levelCollectionNavigationController");
            Logger.Debug("Acquired LevelCollectionNavigationController [{0}]", LevelCollectionNavigationController.GetInstanceID());

            LevelCollectionViewController = LevelCollectionNavigationController.GetField <LevelCollectionViewController, LevelCollectionNavigationController>("_levelCollectionViewController");
            Logger.Debug("Acquired LevelPackLevelsViewController [{0}]", LevelCollectionViewController.GetInstanceID());

            LevelDetailViewController = LevelCollectionNavigationController.GetField <StandardLevelDetailViewController, LevelCollectionNavigationController>("_levelDetailViewController");
            Logger.Debug("Acquired StandardLevelDetailViewController [{0}]", LevelDetailViewController.GetInstanceID());

            LevelCollectionTableView = this.LevelCollectionViewController.GetField <LevelCollectionTableView, LevelCollectionViewController>("_levelCollectionTableView");
            Logger.Debug("Acquired LevelPackLevelsTableView [{0}]", LevelCollectionTableView.GetInstanceID());

            StandardLevelDetailView = LevelDetailViewController.GetField <StandardLevelDetailView, StandardLevelDetailViewController>("_standardLevelDetailView");
            Logger.Debug("Acquired StandardLevelDetailView [{0}]", StandardLevelDetailView.GetInstanceID());

            BeatmapCharacteristicSelectionViewController = StandardLevelDetailView.GetField <BeatmapCharacteristicSegmentedControlController, StandardLevelDetailView>("_beatmapCharacteristicSegmentedControlController");
            Logger.Debug("Acquired BeatmapCharacteristicSegmentedControlController [{0}]", BeatmapCharacteristicSelectionViewController.GetInstanceID());

            LevelDifficultyViewController = StandardLevelDetailView.GetField <BeatmapDifficultySegmentedControlController, StandardLevelDetailView>("_beatmapDifficultySegmentedControlController");
            Logger.Debug("Acquired BeatmapDifficultySegmentedControlController [{0}]", LevelDifficultyViewController.GetInstanceID());

            LevelCollectionTableViewTransform = LevelCollectionTableView.transform as RectTransform;
            Logger.Debug("Acquired TableViewRectTransform from LevelPackLevelsTableView [{0}]", LevelCollectionTableViewTransform.GetInstanceID());

            AnnotatedBeatmapLevelCollectionsViewController = LevelFilteringNavigationController.GetField <AnnotatedBeatmapLevelCollectionsViewController, LevelFilteringNavigationController>("_annotatedBeatmapLevelCollectionsViewController");
            Logger.Debug("Acquired AnnotatedBeatmapLevelCollectionsViewController from LevelFilteringNavigationController [{0}]", AnnotatedBeatmapLevelCollectionsViewController.GetInstanceID());

            TableView  tableView  = LevelCollectionTableView.GetField <TableView, LevelCollectionTableView>("_tableView");
            ScrollView scrollView = tableView.GetField <ScrollView, TableView>("_scrollView");

            TableViewPageUpButton   = scrollView.GetField <Button, ScrollView>("_pageUpButton");
            TableViewPageDownButton = scrollView.GetField <Button, ScrollView>("_pageDownButton");
            Logger.Debug("Acquired Page Up and Down buttons...");

            ActionButtons = StandardLevelDetailView.GetComponentsInChildren <RectTransform>().First(x => x.name == "ActionButtons");
            Logger.Debug("Acquired ActionButtons [{0}]", ActionButtons.GetInstanceID());

            ScreenSystem = Resources.FindObjectsOfTypeAll <ScreenSystem>().Last();
            Logger.Debug("Acquired ScreenSystem [{0}]", ScreenSystem.GetInstanceID());

            SimpleDialogPromptViewControllerPrefab = Resources.FindObjectsOfTypeAll <SimpleDialogPromptViewController>().Last();
            Logger.Debug("Acquired SimpleDialogPromptViewControllerPrefab [{0}]", SimpleDialogPromptViewControllerPrefab.GetInstanceID());

            BeatmapLevelsModel = Resources.FindObjectsOfTypeAll <BeatmapLevelsModel>().Last();
            Logger.Debug("Acquired BeatmapLevelsModel [{0}]", BeatmapLevelsModel);
        }
Example #3
0
 public LTUI(Config config, StandardLevelDetailViewController standardLevelDetailViewController)
 {
     Y2Pos   = -100f;
     _config = config;
     _standardLevelDetailViewController = standardLevelDetailViewController;
     _detailView = standardLevelDetailViewController.GetField <StandardLevelDetailView, StandardLevelDetailViewController>("_standardLevelDetailView");
     _beatmapCharacteristicSegmentedControlController = _detailView.GetField <BeatmapCharacteristicSegmentedControlController, StandardLevelDetailView>("_beatmapCharacteristicSegmentedControlController");
 }
Example #4
0
        public override void Instantiate()
        {
            //We have to find our own target
            //TODO: Clean up time complexity issue. This is called for each new option
            StandardLevelDetailViewController _sldvc = Resources.FindObjectsOfTypeAll <StandardLevelDetailViewController>().First();
            GameplayOptionsViewController     _govc  = _sldvc.GetField <GameplayOptionsViewController>("_gameplayOptionsViewController");
            RectTransform container = (RectTransform)_govc.transform.Find("Switches").Find("Container");

            var volumeSettings = Resources.FindObjectsOfTypeAll <VolumeSettingsController>().FirstOrDefault();

            gameObject      = UnityEngine.Object.Instantiate(volumeSettings.gameObject, container);
            gameObject.name = optionName;
            gameObject.GetComponentInChildren <TMP_Text>().text = optionName;

            //Slim down the toggle option so it fits in the space we have before the divider
            (gameObject.transform as RectTransform).sizeDelta = new Vector2(50, (gameObject.transform as RectTransform).sizeDelta.y);

            //This magical nonsense is courtesy of Taz and his SettingsUI class
            VolumeSettingsController volume = gameObject.GetComponent <VolumeSettingsController>();
            ListViewController       newListSettingsController = (ListViewController)ReflectionUtil.CopyComponent(volume, typeof(ListSettingsController), typeof(ListViewController), gameObject);

            UnityEngine.Object.DestroyImmediate(volume);

            newListSettingsController.values   = _options.Keys.ToList();
            newListSettingsController.SetValue = OnChange;
            newListSettingsController.GetValue = () =>
            {
                if (GetValue != null)
                {
                    return(GetValue.Invoke());
                }
                return(_options.Keys.ElementAt(0));
            };
            newListSettingsController.GetTextForValue = (v) =>
            {
                if (_options.ContainsKey(v))
                {
                    return(_options[v]);
                }
                return("UNKNOWN");
            };

            //Initialize the controller, as if we had just opened the settings menu
            newListSettingsController.Init();
            gameObject.SetActive(false);
        }
Example #5
0
        void Constractor(GameplaySetupViewController container, PlayerDataModel model, StandardLevelDetailViewController standard)
        {
            this.CreateParams();
            this.gameplaySetupViewController = container;
            this.playerDataModel             = model;
            var detailview = standard.GetField <StandardLevelDetailView, StandardLevelDetailViewController>("_standardLevelDetailView");

            this._actionButton = detailview.actionButton;
            if (this._actionButton is NoTransitionsButton noTransitionsButton)
            {
                foreach (var bg in noTransitionsButton.gameObject.GetComponentsInChildren <ImageView>())
                {
                    if (bg.name == "BG")
                    {
                        bg.SetField("_gradient", false);
                        this._defaultColor = bg.color;
                    }
                }
            }
            this.playerSettingsPanelController = this.gameplaySetupViewController.GetField <PlayerSettingsPanelController, GameplaySetupViewController>("_playerSettingsPanelController");
        }
Example #6
0
        public override void Instantiate()
        {
            //We have to find our own target
            //TODO: Clean up time complexity issue. This is called for each new option
            StandardLevelDetailViewController _sldvc = Resources.FindObjectsOfTypeAll <StandardLevelDetailViewController>().First();
            GameplayOptionsViewController     _govc  = _sldvc.GetField <GameplayOptionsViewController>("_gameplayOptionsViewController");
            RectTransform container = (RectTransform)_govc.transform.Find("Switches").Find("Container");

            //TODO: Can probably slim this down a bit
            gameObject = UnityEngine.Object.Instantiate(container.Find("NoEnergy").gameObject, container);
            gameObject.GetComponentInChildren <TextMeshProUGUI>().text = optionName;
            gameObject.name                    = optionName;
            gameObject.layer                   = container.gameObject.layer;
            gameObject.transform.parent        = container;
            gameObject.transform.localPosition = Vector3.zero;
            gameObject.transform.localScale    = Vector3.one;
            gameObject.transform.rotation      = Quaternion.identity;
            gameObject.SetActive(false); //All options start disabled

            gameObject.GetComponentInChildren <HMUI.Toggle>().isOn            = GetValue;
            gameObject.GetComponentInChildren <HMUI.Toggle>().didSwitchEvent += (_, e) => { OnToggle?.Invoke(e); };
        }
Example #7
0
        public void Update()
        {
            if (gamePauseManager.pause)
            {
                return;                         //Don't do anything if we're paused
            }
            //if (audioTimeSyncController.songTime > 10f && playlist.Count > 0 && !_loadingSong)
            if (audioTimeSyncController.songTime >= audioTimeSyncController.songLength - 0.3f && playlist.Count > 0 && !_loadingSong)
            {
                Logger.Debug("Switching song...");

                audioTimeSyncController.StopSong(); //If we don't, there's a chance the song would progress to `songLength - 0.2f` and the base game would finish the game scene

                Logger.Debug($"Current song: {gameplayCoreSceneSetupData.difficultyBeatmap.level.songName}");

                //Clear out old data from objects that would have ideally been recreated
                ClearOldData();

                //Set up new song
                var   gameplayModifiers      = gameplayCoreSceneSetupData.gameplayModifiers;
                var   playerSpecificSettings = gameplayCoreSceneSetupData.playerSpecificSettings;
                float songSpeedMul           = gameplayModifiers.songSpeedMul;

                var level = playlist.Dequeue();

                //Load song if it's a custom level
                if (level is CustomPreviewBeatmapLevel)
                {
                    var task = Task.Run(async() => await SongHelpers.GetLevelFromPreview(level));
                    task.Wait();

                    var result = task.Result;

                    if (result != null && !(result?.isError == true))
                    {
                        level = result?.beatmapLevel;
                    }
                }

                Logger.Debug($"New song: {level.songName}");

                var oldMap = gameplayCoreSceneSetupData.difficultyBeatmap;

                Logger.Debug($"Getting closest difficulty to {gameplayCoreSceneSetupData.difficultyBeatmap.difficulty} with characteristic {gameplayCoreSceneSetupData.difficultyBeatmap.parentDifficultyBeatmapSet.beatmapCharacteristic}...");
                IDifficultyBeatmap map = SongHelpers.GetClosestDifficultyPreferLower(level as IBeatmapLevel, (BeatmapDifficulty)preferredDifficulty, gameplayCoreSceneSetupData.difficultyBeatmap.parentDifficultyBeatmapSet.beatmapCharacteristic);

                Logger.Debug($"Got: {map.difficulty} ({map.parentDifficultyBeatmapSet.beatmapCharacteristic})");

                gameplayCoreSceneSetupData.SetField("_difficultyBeatmap", map);
                BeatmapData beatmapData = BeatDataTransformHelper.CreateTransformedBeatmapData(map.beatmapData, gameplayModifiers, gameplayCoreSceneSetupData.practiceSettings, gameplayCoreSceneSetupData.playerSpecificSettings);
                beatmapDataModel.beatmapData = beatmapData;

                //If this is the last song, set up the viewcontrollers in a way that the proper data is displayed after the song
                var currentPack            = levelDetailViewController.GetField <IBeatmapLevelPack>("_pack");
                var currentPlayer          = levelDetailViewController.GetField <PlayerData>("_playerData");
                var currentShowPlayerStats = levelDetailViewController.GetField <bool>("_showPlayerStats");
                levelDetailViewController.SetData(currentPack, map.level, currentPlayer, currentShowPlayerStats);

                audioTimeSyncController.Init(map.level.beatmapLevelData.audioClip, 0f, map.level.songTimeOffset, songSpeedMul);
                beatmapObjectSpawnController.Init(level.beatsPerMinute, beatmapData.beatmapLinesData.Length, gameplayModifiers.fastNotes ? 20f : (map.noteJumpMovementSpeed == 0 ? map.difficulty.NoteJumpMovementSpeed() : map.noteJumpMovementSpeed), map.noteJumpStartBeatOffset, gameplayModifiers.disappearingArrows, gameplayModifiers.ghostNotes);
                pauseMenuManager.Init(map.level.songName, map.level.songSubName, map.difficulty.Name());

                //Deal with characteristic issues
                Saber.SaberType saberType;
                if (gameplayCoreSceneSetup.UseOneSaberOnly(map.parentDifficultyBeatmapSet.beatmapCharacteristic, playerSpecificSettings, out saberType))
                {
                    gameplayCoreSceneSetup.GetField <PlayerController>("_playerController").AllowOnlyOneSaber(saberType);
                }
                else
                {
                    gameplayCoreSceneSetup
                    .GetField <PlayerController>("_playerController")
                    .GetField <SaberManager>("_saberManager")
                    .SetField("_allowOnlyOneSaber", false);
                }

                Logger.Debug("Starting new song...");
                audioTimeSyncController.StartSong();
                Logger.Debug("Song started!");

                songSwitched?.Invoke(oldMap, map);

                _loadingSong = false;
            }
            //else if (audioTimeSyncController.songTime > 10f && (playlist == null || playlist.Count <= 0) && !_loadingSong)
            else if (audioTimeSyncController.songTime >= audioTimeSyncController.songLength - 0.3f && (playlist == null || playlist.Count <= 0))
            {
                _loadingSong = true; //Only show the following log message once
                Logger.Debug($"Would have switched songs, but playlist was null ({playlist == null}) or empty ({playlist?.Count <= 0})");
            }
        }
Example #8
0
        private void AddMenuOption()
        {
            Transform dropdownTemplate     = _gameplaySetupViewController.transform.Find("EnvironmentOverrideSettings/Settings/Elements/NormalLevels");
            Transform otherSettingsContent = _settingsNavigationController.transform.Find("OtherSettings/Content");

            if (!dropdownTemplate)
            {
                Plugin.Log.Error("Dropdown template not found!");
                return;
            }

            if (!otherSettingsContent)
            {
                Plugin.Log.Error("OtherSettings/Content not found!");
                return;
            }

            GameObject gameObject = _container.InstantiatePrefab(dropdownTemplate.gameObject, otherSettingsContent);

            gameObject.name = "LanguageSetting";

            RectTransform rectTransform = gameObject.GetComponent <RectTransform>();

            rectTransform.offsetMin = new Vector2(0, -14.2f);
            rectTransform.offsetMax = new Vector2(0, -7.2f);

            LocalizedTextMeshProUGUI label = gameObject.transform.Find("Label").GetComponent <LocalizedTextMeshProUGUI>();

            label.Key = "SETTINGS_LANGUAGE";

            _container.InstantiateComponent <LanguageSetting>(gameObject);

            Plugin.Log.Debug("Created language setting");

            var textGameObject = new GameObject("SiraLocalizerContributorsText");

            _credits = textGameObject.AddComponent <CurvedTextMeshPro>();

            var textRectTransform = (RectTransform)textGameObject.transform;

            textRectTransform.SetParent(otherSettingsContent, false);
            textRectTransform.offsetMin = new Vector2(-45f, -7.4f);
            textRectTransform.offsetMax = new Vector2(45f, -7.4f);

            _credits.alignment   = TextAlignmentOptions.TopLeft;
            _credits.lineSpacing = -35f;
            _credits.fontSize    = 3f;
            _credits.fontStyle   = FontStyles.Italic;
            _credits.gameObject.SetActive(false);

            foreach (var lang in Localization.Instance.SupportedLanguages)
            {
                if (lang == Language.English)
                {
                    continue;
                }
                var contributors = Localization.Get("LANGUAGE_CONTRIBUTORS", lang);
                var name         = Localization.Get("MENU_LANGUAGE_THIS", lang);
                if (!string.IsNullOrEmpty(contributors))
                {
                    _credits.text += $"<b>{name}</b>   <color=#bababa>{contributors}</color>\n";
                }
            }

            _creditsToggle      = _container.InstantiatePrefabForComponent <Button>(_standardLevelDetailViewController.GetField <StandardLevelDetailView, StandardLevelDetailViewController>("_standardLevelDetailView").practiceButton);
            _creditsToggle.name = "LocalizationCreditsButton";
            UnityEngine.Object.Destroy(_creditsToggle.transform.Find("Content").GetComponent <LayoutElement>());
            _creditsToggle.gameObject.transform.SetParent(otherSettingsContent, false);
            var rect = (_creditsToggle.transform as RectTransform);

            rect.localPosition = new Vector3(-5f, -11f, 0f);

            ContentSizeFitter buttonSizeFitter = _creditsToggle.gameObject.AddComponent <ContentSizeFitter>();

            buttonSizeFitter.verticalFit   = ContentSizeFitter.FitMode.PreferredSize;
            buttonSizeFitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
            LocalizedTextMeshProUGUI localizer = _creditsToggle.GetComponentInChildren <LocalizedTextMeshProUGUI>(true);

            localizer.Key = "CREDITS_TITLE";

            _creditsToggle.onClick.AddListener(ToggleCredits);
        }
        protected override void DidActivate(bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling)
        {
            if (firstActivation)
            {
                //Set up UI
                SetTitle("Game Room", ViewController.AnimationType.None);

                showBackButton = true;

                _playerDataModel                   = Resources.FindObjectsOfTypeAll <PlayerDataModel>().First();
                _menuLightsManager                 = Resources.FindObjectsOfTypeAll <MenuLightsManager>().First();
                _soloFreePlayFlowCoordinator       = Resources.FindObjectsOfTypeAll <SoloFreePlayFlowCoordinator>().First();
                _standardLevelDetailViewController = Resources.FindObjectsOfTypeAll <StandardLevelDetailViewController>().First();
                _standardLevelDetailView           = _standardLevelDetailViewController.GetField <StandardLevelDetailView, StandardLevelDetailViewController>("_standardLevelDetailView");
                _resultsViewController             = Resources.FindObjectsOfTypeAll <ResultsViewController>().First();
                _scoreLights   = _soloFreePlayFlowCoordinator.GetField <MenuLightsPresetSO>("_resultsClearedLightsPreset");
                _defaultLights = _soloFreePlayFlowCoordinator.GetField <MenuLightsPresetSO>("_defaultLightsPreset");

                _songSelection = BeatSaberUI.CreateViewController <SongSelection>();
                _songSelection.SongSelected += SongSelection_SongSelected;

                _splashScreen = BeatSaberUI.CreateViewController <SplashScreen>();

                _songDetail              = BeatSaberUI.CreateViewController <SongDetail>();
                _songDetail.PlayPressed += SongDetail_didPressPlayButtonEvent;
                _songDetail.DifficultyBeatmapChanged += SongDetail_didChangeDifficultyBeatmapEvent;

                _playerList = BeatSaberUI.CreateViewController <PlayerList>();
            }
            if (addedToHierarchy)
            {
                TournamentMode = Match == null;
                if (TournamentMode)
                {
                    _splashScreen.StatusText = $"Connecting to \"{Host.Name}\"...";
                    ProvideInitialViewControllers(_splashScreen);
                }
                else
                {
                    //If we're not in tournament mode, then a client connection has already been made
                    //by the room selection screen, so we can just assume Plugin.client isn't null
                    //NOTE: This is *such* a hack. Oh my god.
                    isHost = Match.Leader == Plugin.client.Self;
                    _songSelection.SetSongs(SongUtils.masterLevelList);
                    _playerList.Players      = Match.Players;
                    _splashScreen.StatusText = "Waiting for the host to select a song...";

                    if (isHost)
                    {
                        ProvideInitialViewControllers(_songSelection, _playerList);
                    }
                    else
                    {
                        ProvideInitialViewControllers(_splashScreen, _playerList);
                    }
                }
            }

            //The ancestor sets up the server event listeners
            //It would be possible to recieve an event that does a ui update after this call
            //and before the rest of the ui is set up, if we did this at the top.
            //So, we do it last
            base.DidActivate(firstActivation, addedToHierarchy, screenSystemEnabling);
        }
Example #10
0
        public static void Build()
        {
            //Grab necessary references
            StandardLevelDetailViewController _sldvc = Resources.FindObjectsOfTypeAll <StandardLevelDetailViewController>().First();
            GameplayOptionsViewController     _govc  = _sldvc.GetField <GameplayOptionsViewController>("_gameplayOptionsViewController");

            //Get reference to the switch container
            RectTransform container = (RectTransform)_govc.transform.Find("Switches").Find("Container");

            container.sizeDelta = new Vector2(container.sizeDelta.x, container.sizeDelta.y + 7f); //Grow container so it aligns properly with text

            //Get references to the original switches, so we can later duplicate then destroy them
            Transform noEnergyOriginal     = container.Find("NoEnergy");
            Transform noObstaclesOriginal  = container.Find("NoObstacles");
            Transform mirrorOriginal       = container.Find("Mirror");
            Transform staticLightsOriginal = container.Find("StaticLights");

            //Get references to other UI elements we need to hide
            //Transform divider = (RectTransform)_govc.transform.Find("Switches").Find("Separator");
            //Transform defaults = (RectTransform)_govc.transform.Find("Switches").Find("DefaultsButton");

            //Future duplicated switches
            Transform noEnergy     = null;
            Transform noObstacles  = null;
            Transform mirror       = null;
            Transform staticLights = null;

            //Future down button
            Button _pageDownButton = null;

            //Create up button
            Button _pageUpButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().First(x => (x.name == "PageUpButton")), container);

            _pageUpButton.transform.parent     = container;
            _pageUpButton.transform.localScale = Vector3.one;
            (_pageUpButton.transform as RectTransform).sizeDelta = new Vector2((_pageUpButton.transform.parent as RectTransform).sizeDelta.x, 3.5f);
            _pageUpButton.onClick.AddListener(delegate()
            {
                Instance.ChangePage(--Instance._listIndex, container, noEnergy, noObstacles, mirror, staticLights);

                //Nice responsive scroll buttons
                if (Instance._listIndex <= 0)
                {
                    _pageUpButton.interactable = false;
                }
                if (Instance.customOptions.Count > 0)
                {
                    _pageDownButton.interactable = true;
                }
            });
            _pageUpButton.interactable = false;

            //Duplicate and delete default toggles so that the up button is on the top
            noEnergy     = Instantiate(noEnergyOriginal, container);
            noObstacles  = Instantiate(noObstaclesOriginal, container);
            mirror       = Instantiate(mirrorOriginal, container);
            staticLights = Instantiate(staticLightsOriginal, container);

            //Create custom options
            foreach (object option in Instance.customOptions)
            {
                //Due to possible "different" types (due to cross-plugin support), we need to do this through reflection
                option.InvokeMethod("Instantiate");
            }

            //Destroy original toggles and set their corresponding references to the new toggles
            DestroyImmediate(noEnergyOriginal.gameObject);
            DestroyImmediate(noObstaclesOriginal.gameObject);
            DestroyImmediate(mirrorOriginal.gameObject);
            DestroyImmediate(staticLightsOriginal.gameObject);

            _govc.SetField("_noEnergyToggle", noEnergy.gameObject.GetComponentInChildren <HMUI.Toggle>());
            _govc.SetField("_noObstaclesToggle", noObstacles.gameObject.GetComponentInChildren <HMUI.Toggle>());
            _govc.SetField("_mirrorToggle", mirror.gameObject.GetComponentInChildren <HMUI.Toggle>());
            _govc.SetField("_staticLightsToggle", staticLights.gameObject.GetComponentInChildren <HMUI.Toggle>());

            //Create down button
            _pageDownButton = Instantiate(Resources.FindObjectsOfTypeAll <Button>().First(x => (x.name == "PageDownButton")), container);
            _pageDownButton.transform.parent     = container;
            _pageDownButton.transform.localScale = Vector3.one;
            (_pageDownButton.transform as RectTransform).sizeDelta = new Vector2((_pageDownButton.transform.parent as RectTransform).sizeDelta.x, (_pageDownButton.transform as RectTransform).sizeDelta.y);
            _pageDownButton.onClick.AddListener(delegate()
            {
                Instance.ChangePage(++Instance._listIndex, container, noEnergy, noObstacles, mirror, staticLights);

                //Nice responsive scroll buttons
                if (Instance._listIndex >= 0)
                {
                    _pageUpButton.interactable = true;
                }
                if (((Instance.customOptions.Count + 4 - 1) / 4) - Instance._listIndex <= 0)
                {
                    _pageDownButton.interactable = false;
                }
            });
            _pageDownButton.interactable = Instance.customOptions.Count > 0;

            //Unfortunately, due to weird object creation for versioning, this doesn't always
            //happen when the scene changes
            Instance._listIndex = 0;
        }