public void SetDefaultValues()
        {
            if (!_isInitialized || !Tweaks.SongDataCoreTweaks.ModLoaded)
            {
                return;
            }

            _rankedStagingValue     = RankFilterOption.Off;
            _minEnabledStagingValue = false;
            _maxEnabledStagingValue = false;
            _minStagingValue        = DefaultMinValue;
            _maxStagingValue        = DefaultMaxValue;

            _container.SetActive(false);
            _minViewController.GetComponentInChildren <Toggle>().isOn = false;
            _maxViewController.GetComponentInChildren <Toggle>().isOn = false;
            RefreshUI();
        }
        public void ResetValues()
        {
            if (!_isInitialized || !Tweaks.SongDataCoreTweaks.ModLoaded)
            {
                return;
            }

            _rankedStagingValue     = _rankedAppliedValue;
            _minEnabledStagingValue = _minEnabledAppliedValue;
            _maxEnabledStagingValue = _maxEnabledAppliedValue;
            _minStagingValue        = _minAppliedValue;
            _maxStagingValue        = _maxAppliedValue;

            _container.SetActive(_rankedStagingValue == RankFilterOption.Ranked);
            _minViewController.GetComponentInChildren <Toggle>().isOn = _minEnabledAppliedValue;
            _maxViewController.GetComponentInChildren <Toggle>().isOn = _maxEnabledAppliedValue;
            RefreshUI();
        }
        public void Init()
        {
            if (_isInitialized)
            {
                return;
            }

            if (!Tweaks.SongDataCoreTweaks.ModLoaded)
            {
                Controls = new FilterControl[1];

                var noModMessage = BeatSaberUI.CreateText(null, "<color=#FFAAAA>Sorry!\n\n<size=80%>This filter requires the SongDataCore mod to be\n installed.</size></color>", Vector2.zero);
                noModMessage.alignment = TextAlignmentOptions.Center;
                noModMessage.fontSize  = 5.5f;

                Controls[0] = new FilterControl(noModMessage.gameObject, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(80f, 50f), new Vector2(0f, 10f));

                _isInitialized = true;
                return;
            }

            // title text
            var text = BeatSaberUI.CreateText(null, "Keep Songs That Award PP", Vector2.zero, Vector2.zero);

            text.fontSize = 5.5f;
            var rt = text.rectTransform;

            rt.anchorMin = new Vector2(0f, 1f);
            rt.anchorMax = new Vector2(0f, 1f);
            rt.pivot     = new Vector2(0f, 1f);

            Controls[0] = new FilterControl(text.gameObject, new Vector2(0f, 0.95f), new Vector2(0f, 0.95f), new Vector2(0f, 1f), new Vector2(50f, 6f), Vector2.zero);

            // ranked view controller
            float[] rankedValues = Enumerable.Range(0, Enum.GetValues(typeof(RankFilterOption)).Length).Select(x => (float)x).ToArray();
            _rankedViewController = Utilities.CreateListViewController("Is Ranked", rankedValues, "Filters out songs depending on whether they are ranked");
            _rankedViewController.GetTextForValue += delegate(float value)
            {
                RankFilterOption option = (RankFilterOption)value;
                if (option == RankFilterOption.Ranked)
                {
                    return("Ranked");
                }
                else if (option == RankFilterOption.NotRanked)
                {
                    return("<size=80%>Not Ranked</size>");
                }
                else
                {
                    return("Off");
                }
            };
            _rankedViewController.GetValue += () => (float)_rankedStagingValue;
            _rankedViewController.SetValue += delegate(float value)
            {
                _rankedStagingValue = (RankFilterOption)value;

                if (_rankedStagingValue == RankFilterOption.Ranked)
                {
                    _container.SetActive(true);

                    _minViewController.transform.Find("MinValueToggle").GetComponent <Toggle>().isOn = _minEnabledStagingValue;
                    _maxViewController.transform.Find("MaxValueToggle").GetComponent <Toggle>().isOn = _maxEnabledStagingValue;
                }
                else
                {
                    _container.SetActive(false);
                    _minEnabledStagingValue = false;
                    _maxEnabledStagingValue = false;
                }

                SettingChanged?.Invoke();
            };
            _rankedViewController.Init();
            _rankedViewController.applyImmediately = true;

            Utilities.MoveListViewControllerElements(_rankedViewController);

            Controls[1] = new FilterControl(_rankedViewController.gameObject, new Vector2(0f, 0.95f), new Vector2(1f, 0.95f), new Vector2(0.5f, 1f), new Vector2(0f, 12f), new Vector2(0f, -8f));

            // min-max view controller container
            _container = new GameObject("PPFilterContainer");
            var unused = _container.AddComponent <Image>();

            unused.color    = new Color(0f, 0f, 0f, 0f);
            unused.material = Utilities.NoGlowMaterial;

            var togglePrefab = Utilities.GetTogglePrefab();

            // min view controller
            float[] values = Enumerable.Range((int)MinValue, (int)((MaxValue - MinValue) / IncrementValue) + 1).Select(x => x * IncrementValue).ToArray();
            _minViewController = Utilities.CreateListViewController("Minimum PP", values, "Filters out ranked songs that award less PP that this value");
            _minViewController.GetTextForValue += x => x.ToString();
            _minViewController.GetValue        += () => _minStagingValue;
            _minViewController.SetValue        += delegate(float value)
            {
                if (_maxEnabledStagingValue && value > _maxStagingValue)
                {
                    _minStagingValue = _maxStagingValue;
                    RefreshUI();
                    return;
                }

                _minStagingValue = value;

                RefreshUI(false);

                SettingChanged?.Invoke();
            };
            _minViewController.Init();
            _minViewController.applyImmediately = true;

            rt = _minViewController.transform as RectTransform;
            rt.SetParent(_container.transform);
            rt.anchorMin        = new Vector2(0f, 1f);
            rt.anchorMax        = Vector2.one;
            rt.pivot            = new Vector2(0.5f, 1f);
            rt.anchoredPosition = Vector2.zero;
            rt.sizeDelta        = new Vector2(0f, 12f);

            var minToggle = Utilities.CreateToggleFromPrefab(togglePrefab.toggle, _minViewController.transform.Find("Value"));

            minToggle.name = "MinValueToggle";
            minToggle.onValueChanged.AddListener(delegate(bool value)
            {
                _minEnabledStagingValue = value;

                if (value && _maxEnabledStagingValue && _minStagingValue > _maxStagingValue)
                {
                    _minStagingValue = _maxStagingValue;
                }

                RefreshUI(true, true);

                SettingChanged?.Invoke();
            });

            Utilities.MoveListViewControllerElements(_minViewController);
            var divider = Utilities.CreateHorizontalDivider(_minViewController.transform, false);

            divider.color = new Color(1f, 1f, 1f, 0.4f);
            divider.rectTransform.sizeDelta = new Vector2(0f, 0.2f);
            Utilities.CreateHorizontalDivider(_minViewController.transform);

            // max view controller
            _maxViewController = Utilities.CreateListViewController("Maximum PP", values, "Filters out ranked songs that award more PP that this value");
            _maxViewController.GetTextForValue += x => x.ToString();
            _maxViewController.GetValue        += () => _maxStagingValue;
            _maxViewController.SetValue        += delegate(float value)
            {
                if (_minEnabledStagingValue && value < _minStagingValue)
                {
                    _maxStagingValue = _minStagingValue;
                    RefreshUI();
                    return;
                }

                _maxStagingValue = value;

                RefreshUI(false);

                SettingChanged?.Invoke();
            };
            _maxViewController.Init();
            _maxViewController.applyImmediately = true;

            rt = _maxViewController.transform as RectTransform;
            rt.SetParent(_container.transform);
            rt.anchorMin        = new Vector2(0f, 1f);
            rt.anchorMax        = Vector2.one;
            rt.pivot            = new Vector2(0.5f, 1f);
            rt.anchoredPosition = new Vector2(0f, -12f);
            rt.sizeDelta        = new Vector2(0f, 12f);

            var maxToggle = Utilities.CreateToggleFromPrefab(togglePrefab.toggle, _maxViewController.transform.Find("Value"));

            maxToggle.name = "MaxValueToggle";
            maxToggle.onValueChanged.AddListener(delegate(bool value)
            {
                _maxEnabledStagingValue = value;

                if (value && _minEnabledStagingValue && _maxStagingValue < _minStagingValue)
                {
                    _maxStagingValue = _minStagingValue;
                }

                RefreshUI(true, true);

                SettingChanged?.Invoke();
            });

            Utilities.MoveListViewControllerElements(_maxViewController);

            Object.Destroy(togglePrefab);

            Controls[2] = new FilterControl(_container, new Vector2(0f, 0.95f), new Vector2(1f, 0.95f), new Vector2(0.5f, 1f), new Vector2(0f, 24f), new Vector2(0f, -20f),
                                            delegate()
            {
                _container.SetActive(_rankedStagingValue == RankFilterOption.Ranked);

                minToggle.isOn = _minEnabledStagingValue;
                maxToggle.isOn = _maxEnabledStagingValue;
            });

            _isInitialized = true;
        }