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));
            }
        }
        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));
            }
        }
        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);
        }