Example #1
0
        private void CalculateSafeAreaAndCutouts()
        {
            var  orientationData  = m_SupportedOrientations[m_RenderedOrientation];
            var  safeArea         = orientationData.safeArea;
            Rect onScreenSafeArea = new Rect();

            // Calculating where on the screen to draw safe area
            onScreenSafeArea = safeArea;
            switch (m_RenderedOrientation)
            {
            case ScreenOrientation.Portrait:
                onScreenSafeArea.y = m_Screen.height - safeArea.height - safeArea.y;
                break;

            case ScreenOrientation.PortraitUpsideDown:
                break;

            case ScreenOrientation.LandscapeLeft:
                onScreenSafeArea.y      = safeArea.x;
                onScreenSafeArea.x      = safeArea.y;
                onScreenSafeArea.height = safeArea.width;
                onScreenSafeArea.width  = safeArea.height;
                break;

            case ScreenOrientation.LandscapeRight:
                onScreenSafeArea.y      = m_Screen.height - safeArea.width - safeArea.x;
                onScreenSafeArea.x      = m_Screen.width - safeArea.height - safeArea.y;
                onScreenSafeArea.width  = safeArea.height;
                onScreenSafeArea.height = safeArea.width;
                break;
            }

            if (!m_IsFullScreen)
            {
                switch (m_RenderedOrientation)
                {
                case ScreenOrientation.PortraitUpsideDown:
                    onScreenSafeArea.yMin += m_Screen.navigationBarHeight;
                    break;

                case ScreenOrientation.LandscapeLeft:
                case ScreenOrientation.LandscapeRight:
                case ScreenOrientation.Portrait:
                    onScreenSafeArea.yMax -= m_Screen.navigationBarHeight;
                    break;
                }
            }

            ScreenSpaceSafeArea = onScreenSafeArea;
            OnScreenSpaceSafeAreaChanged?.Invoke(ScreenSpaceSafeArea);

            var screenWidthInOrientation  = IsRenderingLandscape ? m_Screen.height : m_Screen.width;
            var screenHeightInOrientation = IsRenderingLandscape ? m_Screen.width : m_Screen.height;

            // The inverse of safe area, that is the size of borders excluded from the safe area.
            // It is more convenient to scale these borders to correct resolution than to scale safe area rect.
            var unsafeBorders = new Vector4()
            {
                x = safeArea.x,
                y = screenHeightInOrientation - safeArea.height - safeArea.y,
                z = screenWidthInOrientation - safeArea.width - safeArea.x,
                w = safeArea.y
            };

            // Need to exclude unsafe area hidden by insets. It is obscured by the inset and therefore disappears.
            var insetsInOrientation = InsetsInCurrentOrientation;

            unsafeBorders -= insetsInOrientation;

            // A negative unsafe border can happen because inset encroaches on the safe area. In other words, unsafe border is smaller than the inset.
            // In these cases the safe area will border the inset directly on that side of the screen, so unsafe border is clamped to 0.
            unsafeBorders.x = Mathf.Clamp(unsafeBorders.x, 0, float.MaxValue);
            unsafeBorders.y = Mathf.Clamp(unsafeBorders.y, 0, float.MaxValue);
            unsafeBorders.z = Mathf.Clamp(unsafeBorders.z, 0, float.MaxValue);
            unsafeBorders.w = Mathf.Clamp(unsafeBorders.w, 0, float.MaxValue);

            // This is the resolution of the part of the screen where game rendering is occuring, it might be different than the actual rendering resolution.
            var renderAreaWidth  = screenWidthInOrientation - insetsInOrientation.x - insetsInOrientation.z;
            var renderAreaHeight = screenHeightInOrientation - insetsInOrientation.y - insetsInOrientation.w;

            var resolutionWidthScale  = m_CurrentWidth / renderAreaWidth;
            var resolutionHeightScale = m_CurrentHeight / renderAreaHeight;

            unsafeBorders.x *= resolutionWidthScale;
            unsafeBorders.y *= resolutionHeightScale;
            unsafeBorders.z *= resolutionWidthScale;
            unsafeBorders.w *= resolutionHeightScale;

            m_CurrentSafeArea = new Rect(Mathf.Round(unsafeBorders.x), Mathf.Round(unsafeBorders.w), Mathf.Round(m_CurrentWidth - unsafeBorders.x - unsafeBorders.z), Mathf.Round(m_CurrentHeight - unsafeBorders.y - unsafeBorders.w));

            if (orientationData.cutouts == null || orientationData.cutouts.Length == 0)
            {
                m_CurrentCutouts = new Rect[0];
            }
            else
            {
                // Calculating the cutouts and adding the ones that are inside the rendering area.
                List <Rect> currentCutouts = new List <Rect>();

                for (int i = 0; i < orientationData.cutouts.Length; ++i)
                {
                    var cutout        = orientationData.cutouts[i];
                    var currentCutout = new Rect(Mathf.Round((cutout.x - insetsInOrientation.x) * resolutionWidthScale), Mathf.Round((cutout.y - insetsInOrientation.w) * resolutionHeightScale), Mathf.Round(cutout.width * resolutionWidthScale), Mathf.Round(cutout.height * resolutionHeightScale));

                    // Negative coordinates can happen if the cutout overlaps the inset. In other words, if the cutout is outside the rendering area.
                    if (currentCutout.x >= 0 && currentCutout.y >= 0 && currentCutout.xMax <= m_CurrentWidth && currentCutout.yMax <= m_CurrentHeight)
                    {
                        currentCutouts.Add(currentCutout);
                    }
                }

                m_CurrentCutouts = currentCutouts.ToArray();
            }
        }
Example #2
0
        private void CalculateSafeAreaAndCutouts()
        {
            var  safeArea         = m_SupportedOrientations[m_RenderedOrientation].safeArea;
            Rect onScreenSafeArea = new Rect();

            // Calculating where on the screen to draw safe area
            onScreenSafeArea = safeArea;
            switch (m_RenderedOrientation)
            {
            case ScreenOrientation.Portrait:
                onScreenSafeArea.y = m_Screen.height - safeArea.height - safeArea.y;
                break;

            case ScreenOrientation.PortraitUpsideDown:
                break;

            case ScreenOrientation.LandscapeLeft:
                onScreenSafeArea.y      = safeArea.x;
                onScreenSafeArea.x      = safeArea.y;
                onScreenSafeArea.height = safeArea.width;
                onScreenSafeArea.width  = safeArea.height;
                break;

            case ScreenOrientation.LandscapeRight:
                onScreenSafeArea.y      = m_Screen.height - safeArea.width - safeArea.x;
                onScreenSafeArea.x      = m_Screen.width - safeArea.height - safeArea.y;
                onScreenSafeArea.width  = safeArea.height;
                onScreenSafeArea.height = safeArea.width;
                break;
            }

            if (!m_IsFullScreen)
            {
                switch (m_RenderedOrientation)
                {
                case ScreenOrientation.PortraitUpsideDown:
                    onScreenSafeArea.yMin += m_Screen.navigationBarHeight;
                    break;

                case ScreenOrientation.LandscapeLeft:
                case ScreenOrientation.LandscapeRight:
                case ScreenOrientation.Portrait:
                    onScreenSafeArea.yMax -= m_Screen.navigationBarHeight;
                    break;
                }
            }

            ScreenSpaceSafeArea = onScreenSafeArea;
            OnScreenSpaceSafeAreaChanged?.Invoke(ScreenSpaceSafeArea);

            int scaledHeight = 0;
            var scaledNavigationBarHeight = Mathf.RoundToInt(m_DpiRatio * m_Screen.navigationBarHeight);

            if (!m_WasResolutionSet)
            {
                scaledHeight = scaledNavigationBarHeight;
                if (m_SupportedOrientations.ContainsKey(ScreenOrientation.Portrait))
                {
                    scaledHeight += Mathf.RoundToInt(m_DpiRatio * (m_Screen.height - m_SupportedOrientations[ScreenOrientation.Portrait].safeArea.height));
                }
            }

            // Always consider the full screen mode width/height to scale the safe area & cutouts.
            float xScale, yScale;

            if (IsRenderingLandscape)
            {
                xScale = (float)(m_CurrentWidth + (m_IsFullScreen ? 0 : scaledHeight)) / m_Screen.height;
                yScale = (float)m_CurrentHeight / m_Screen.width;
            }
            else
            {
                xScale = (float)m_CurrentWidth / m_Screen.width;
                yScale = (float)(m_CurrentHeight + (m_IsFullScreen ? 0 : scaledHeight)) / m_Screen.height;
            }

            // Scale safe area.
            var odd = m_SupportedOrientations[m_RenderedOrientation];
            var sa  = odd.safeArea;

            if (m_IsFullScreen)
            {
                m_CurrentSafeArea = new Rect(Mathf.Round(sa.x * xScale), Mathf.Round(sa.y * yScale), Mathf.Round(sa.width * xScale), Mathf.Round(sa.height * yScale));
            }
            else
            {
                if (m_WasResolutionSet)
                {
                    m_CurrentSafeArea = new Rect(0, 0, m_CurrentWidth, m_CurrentHeight); // Set the safe area to current resolution in windowed mode with resolution set.
                }
                else
                {
                    m_CurrentSafeArea = new Rect(0, 0, Mathf.Round(sa.width * xScale), Mathf.Round(sa.height * yScale));
                }
            }

            // Consider the navigation bar height if it's windowed mode without resolution set.
            if (!m_IsFullScreen && !m_WasResolutionSet)
            {
                switch (m_RenderedOrientation)
                {
                case ScreenOrientation.Portrait:
                case ScreenOrientation.PortraitUpsideDown:
                    m_CurrentSafeArea.height -= scaledNavigationBarHeight;
                    break;

                case ScreenOrientation.LandscapeLeft:
                case ScreenOrientation.LandscapeRight:
                    m_CurrentSafeArea.width -= scaledNavigationBarHeight;
                    break;
                }
            }

            // For windowed mode, let's return empty cutouts for now.
            if (!m_IsFullScreen)
            {
                m_CurrentCutouts = new Rect[0];
                return;
            }

            // Scale cutouts.
            if (odd.cutouts?.Length > 0)
            {
                m_CurrentCutouts = new Rect[odd.cutouts.Length];
                for (int i = 0; i < odd.cutouts.Length; ++i)
                {
                    var cutout = odd.cutouts[i];
                    m_CurrentCutouts[i] = new Rect(Mathf.Round(cutout.x * xScale), Mathf.Round(cutout.y * yScale), Mathf.Round(cutout.width * xScale), Mathf.Round(cutout.height * yScale));
                }
            }
            else
            {
                m_CurrentCutouts = new Rect[0];
            }
        }
Example #3
0
        public void ApplyChanges()
        {
            var updateSafeArea = false;

            var orientationEvent         = false;
            var resolutionEvent          = false;
            var fullScreenEvent          = false;
            var screenSpaceSafeAreaEvent = false;
            var insetsEvent = false;

            if (m_RequestedOrientation != m_RenderedOrientation)
            {
                if (m_RequestedOrientation.IsLandscape() != m_RenderedOrientation.IsLandscape())
                {
                    // Swap resolution Width and Height if changing from Portrait to Landscape or vice versa
                    if (m_WasResolutionSet)
                    {
                        (m_RequestedHeight, m_RequestedWidth) = (m_RequestedWidth, m_RequestedHeight);
                    }
                    else
                    {
                        m_RequestDefaultResolution = true;
                    }
                }

                m_RenderedOrientation = m_RequestedOrientation;
                orientationEvent      = true;
                m_RequestInsetUpdate  = true;
                updateSafeArea        = true;
            }

            if (m_RequestedFullScreen != m_IsFullScreen)
            {
                m_IsFullScreen       = m_RequestedFullScreen;
                m_RequestInsetUpdate = true;

                // We only change the resolution if we never set the resolution by calling Screen.SetResolution().
                if (!m_WasResolutionSet)
                {
                    m_RequestDefaultResolution = true;
                }

                updateSafeArea  = true;
                fullScreenEvent = true;
            }

            if (m_RequestInsetUpdate)
            {
                CalculateInsets();
                insetsEvent = true;
            }

            if ((m_RequestedWidth != m_CurrentWidth || m_RequestedHeight != m_CurrentHeight) && m_WasResolutionSet)
            {
                m_CurrentWidth  = m_RequestedWidth;
                m_CurrentHeight = m_RequestedHeight;
                updateSafeArea  = true;
                resolutionEvent = true;
            }
            else if (m_RequestDefaultResolution)
            {
                CalculateResolutionWithInsets();
                updateSafeArea  = true;
                resolutionEvent = true;
            }

            if (updateSafeArea)
            {
                CalculateSafeAreaAndCutouts();
                screenSpaceSafeAreaEvent = true;
            }

            if (orientationEvent)
            {
                OnOrientationChanged?.Invoke();
            }
            if (resolutionEvent)
            {
                OnResolutionChanged?.Invoke(m_CurrentWidth, m_CurrentHeight);
            }
            if (fullScreenEvent)
            {
                OnFullScreenChanged?.Invoke(m_IsFullScreen);
            }
            if (screenSpaceSafeAreaEvent)
            {
                OnScreenSpaceSafeAreaChanged?.Invoke(ScreenSpaceSafeArea);
            }
            if (insetsEvent)
            {
                OnInsetsChanged?.Invoke(Insets);
            }

            m_RequestDefaultResolution = false;
            m_RequestedOrientation     = m_RenderedOrientation;
            m_RequestedHeight          = m_CurrentHeight;
            m_RequestedWidth           = m_CurrentWidth;
            m_RequestInsetUpdate       = false;
        }