Game Development Community

BUG in GUIControl.OnPreRender

by Scott Goodwin · in Torque X 2D · 02/18/2008 (9:43 am) · 1 replies

In GUIControl.OnPreRender, the cases for wide/non-wide screen are reversed which affects letterboxing.

#region BUG(SDG)
                    // these cases are reversed
#if !SDG_APPLY_BUGFIXES
                    // widescreen 
                    if (GFX.GFXDevice.IsWideScreen((int)_bounds.Width, (int)_bounds.Height))
                    {
                        // calculate as fixed width, adjusting the height based on how wide the 
                        // display is, creating a horizontal letterbox on fullscreen displays
                        newBounds.Width = width;
                        newBounds.Height = width * ratio;

                        if (newBounds.Height > height)
                            newBounds.Height = height;
                    }
 
                    // non-widescreen 
                    else
                    {
                        // calculate as fixed height, adjusting the width based on how tall the
                        // display is, creating a vertical letterbox on widescreen displays
                        newBounds.Height = height;
                        newBounds.Width = height * (1.0f / ratio);

                        if (newBounds.Width > width)
                            newBounds.Width = width;
                    }
#endif
                    #endregion
 
                    #region BUGFIX(SDG)
#if SDG_APPLY_BUGFIXES
                    // non-widescreen 
                    if (!GFX.GFXDevice.IsWideScreen((int)_bounds.Width, (int)_bounds.Height))
                    {
                        // calculate as fixed width, adjusting the height based on how wide the 
                        // display is, creating a horizontal letterbox on fullscreen displays
                        newBounds.Width = width;
                        newBounds.Height = width * ratio;

                        if (newBounds.Height > height)
                            newBounds.Height = height;
                    }
 
                    // widescreen 
                    else
                    {
                        // calculate as fixed height, adjusting the width based on how tall the
                        // display is, creating a vertical letterbox on widescreen displays
                        newBounds.Height = height;
                        newBounds.Width = height * (1.0f / ratio);
 
                        if (newBounds.Width > width)
                            newBounds.Width = width;
                    }
                     
#endif
                    #endregion

#1
03/02/2008 (8:19 pm)
I found some other cases where GUIControl.OnPreRender doesn't play nice...here's my proposed replacement. For a list of some of the problem cases (if anyone wants to doublecheck), see the comments
in the code below.

/// <summary>
        /// Called before GUIControl.OnRender. Allows for any special processing that is
        /// needed before rendering the control.
        /// </summary>
        public virtual void OnPreRender()
        {
            // all bottom level controls should be the same dimensions as the canvas
            //  unless they wish to preserve aspect ratio
 
            #region BUG(SDG)
            // Even with the previous bug fix, this still doesn't work properly in some cases,
            // (all examples have PreserveAspectRatio=true)
            // e.g., canvas 1365x768 with ctrl 1024x768. needsResize is false. ctrl doesn't get centered.
            // e.g., canvas 1365x767 with ctrl 1024x768. needsResize is true. ctrl gets stretched!
            // e.g., canvas 1024x600 with ctrl 1024x768. needsResize is true. ctrl gets stretched!
            // etc. should also check case where isWidescreen=true, _bounds.Width != width,
            // will probably have cases where ctrl doesn't get centered---didn't verify this
            // Instead...let's just start fresh.
#if !SDG_APPLY_BUGFIXES
            if (_style.PreserveAspectRatio)
            {
                float width = GUICanvas.Instance.Bounds.Width;
                float height = GUICanvas.Instance.Bounds.Height;
 
                bool isWidescreen = GFX.GFXDevice.IsWideScreen((int)_bounds.Width, (int)_bounds.Height);
                bool needsResize = isWidescreen ? (_bounds.Width != width) : (_bounds.Height != height);
 
                if (needsResize)
                {
                    RectangleF newBounds = _bounds;
 
                    // calculate preserved aspect dimensions
                    float ratio = _bounds.Height / _bounds.Width;
 
 
            #region BUG(SDG)
                    // these cases are reversed
#if !SDG_APPLY_BUGFIXES
                    // widescreen 
                    if (GFX.GFXDevice.IsWideScreen((int)_bounds.Width, (int)_bounds.Height))
                    {
                        // calculate as fixed width, adjusting the height based on how wide the 
                        // display is, creating a horizontal letterbox on fullscreen displays
                        newBounds.Width = width;
                        newBounds.Height = width * ratio;
 
                        if (newBounds.Height > height)
                            newBounds.Height = height;
                    }
 
                    // non-widescreen 
                    else
                    {
                        // calculate as fixed height, adjusting the width based on how tall the
                        // display is, creating a vertical letterbox on widescreen displays
                        newBounds.Height = height;
                        newBounds.Width = height * (1.0f / ratio);

                        if (newBounds.Width > width)
                            newBounds.Width = width;
                    }
#endif
                    #endregion
 
            #region BUGFIX(SDG)
#if SDG_APPLY_BUGFIXES
                    // non-widescreen 
                    if (!GFXDevice.IsWideScreen((int)_bounds.Width, (int)_bounds.Height))
                    {
                        // calculate as fixed width, adjusting the height based on how wide the 
                        // display is, creating a horizontal letterbox on fullscreen displays
                        newBounds.Width = width;
                        newBounds.Height = width * ratio;
 
                        if (newBounds.Height > height)
                            newBounds.Height = height;
                    }
 
                    // widescreen 
                    else
                    {
                        // calculate as fixed height, adjusting the width based on how tall the
                        // display is, creating a vertical letterbox on widescreen displays
                        newBounds.Height = height;
                        newBounds.Width = height * (1.0f / ratio);
 
                        if (newBounds.Width > width)
                            newBounds.Width = width;
                    }
#endif
                    #endregion
 
                    // calculate center position
                    newBounds.X = (width - newBounds.Width) / 2.0f;
                    newBounds.Y = (height - newBounds.Height) / 2.0f;
 
                    SetBounds(newBounds);
                }
            }
            else
            {
                if (_bounds != GUICanvas.Instance.Bounds)
                    SetBounds(GUICanvas.Instance.Bounds);
            }
#endif
            #endregion
 
            #region BUGFIX(SDG)
            // This is my proposed replacement for the above.
#if SDG_APPLY_BUGFIXES
            if (_style.PreserveAspectRatio)
            {
                float canvasWidth = GUICanvas.Instance.Bounds.Width;
                float canvasHeight = GUICanvas.Instance.Bounds.Height;
                float canvasRatio = canvasHeight / canvasWidth;
 
                float ctrlWidth = _bounds.Width;
                float ctrlHeight = _bounds.Height;
                float ctrlRatio = ctrlHeight / ctrlWidth;
 
                RectangleF newCtrlBounds = _bounds;
 
                if (canvasRatio == ctrlRatio)
                {
                    if (_bounds != GUICanvas.Instance.Bounds)
                        // stretch/shrink
                        SetBounds(GUICanvas.Instance.Bounds);
                }
                else if (canvasRatio > ctrlRatio)
                {
                    newCtrlBounds.Width = canvasWidth;
                    newCtrlBounds.Height = canvasWidth * ctrlRatio;
 
                    if (newCtrlBounds.Height > canvasHeight)
                        newCtrlBounds.Height = canvasHeight;
 
                    // calculate center position
                    newCtrlBounds.X = canvasWidth > newCtrlBounds.Width ? (canvasWidth - newCtrlBounds.Width) / 2.0f : 0;
                    newCtrlBounds.Y = canvasHeight > newCtrlBounds.Height ? (canvasHeight - newCtrlBounds.Height) / 2.0f : 0;
 
                    SetBounds(newCtrlBounds);
                }
                else // if (canvasRatio < ctrlRatio)
                {
                    newCtrlBounds.Height = canvasHeight;
                    newCtrlBounds.Width = canvasHeight * (1.0f / ctrlRatio);
 
                    if (newCtrlBounds.Width > canvasWidth)
                        newCtrlBounds.Width = canvasWidth;
 
                    // calculate center position
                    newCtrlBounds.X = canvasWidth > newCtrlBounds.Width ? (canvasWidth - newCtrlBounds.Width) / 2.0f : 0;
                    newCtrlBounds.Y = canvasHeight > newCtrlBounds.Height ? (canvasHeight - newCtrlBounds.Height) / 2.0f : 0;
 
                    SetBounds(newCtrlBounds);
                }
            }
            else // if (!_style.PreserveAspectRatio)
            {
                if (_bounds != GUICanvas.Instance.Bounds)
                    SetBounds(GUICanvas.Instance.Bounds);
            }
#endif
            #endregion
        }