fixed some long overdue bugs in the boxing viewport adapter

This commit is contained in:
Dylan Wilson
2019-08-18 18:27:48 +10:00
parent b2b90832a0
commit bbd03e4d73
4 changed files with 35 additions and 73 deletions
@@ -40,7 +40,7 @@ namespace Features.Demos
// the boxing viewport adapter uses letterboxing or pillarboxing to maintain aspect ratio
// it's a little more complicated and needs to listen to the window client size changing event
_boxingViewportAdapter = new BoxingViewportAdapter(Window, GraphicsDevice, 800, 480, 88, 70);
_boxingViewportAdapter = new BoxingViewportAdapter(Window, GraphicsDevice, 800, 480);//, 88, 70);
// typically you'll only ever want to use one viewport adapter for a game, but in this sample we'll be
// switching between them.
@@ -68,13 +68,13 @@ namespace Features.Demos
Exit();
if (keyboardState.IsKeyDown(Keys.D))
_currentViewportAdapter = _defaultViewportAdapter;
SwitchAdapter(_defaultViewportAdapter);
if (keyboardState.IsKeyDown(Keys.S))
_currentViewportAdapter = _scalingViewportAdapter;
SwitchAdapter(_scalingViewportAdapter);
if (keyboardState.IsKeyDown(Keys.B))
_currentViewportAdapter = _boxingViewportAdapter;
SwitchAdapter(_boxingViewportAdapter);
// if we've changed the viewport adapter mid game we need to reset the viewport back to the window size
// this wouldn't normally be required if you're only ever using one viewport adapter
@@ -90,6 +90,12 @@ namespace Features.Demos
base.Update(gameTime);
}
private void SwitchAdapter(ViewportAdapter viewportAdapter)
{
_currentViewportAdapter?.Dispose();
_currentViewportAdapter = viewportAdapter;
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
@@ -15,60 +15,26 @@ namespace MonoGame.Extended.ViewportAdapters
public class BoxingViewportAdapter : ScalingViewportAdapter
{
private readonly GraphicsDeviceManager _graphicsDeviceManager;
private readonly GameWindow _window;
private readonly GraphicsDevice _graphicsDevice;
/// <summary>
/// Initializes a new instance of the <see cref="BoxingViewportAdapter" />.
/// Note: If you're using DirectX please use the other constructor due to a bug in MonoGame.
/// https://github.com/mono/MonoGame/issues/4018
/// Initializes a new instance of the <see cref="BoxingViewportAdapter" />.
/// </summary>
public BoxingViewportAdapter(GameWindow window, GraphicsDevice graphicsDevice, int virtualWidth,
int virtualHeight, int horizontalBleed, int verticalBleed)
public BoxingViewportAdapter(GameWindow window, GraphicsDevice graphicsDevice, int virtualWidth, int virtualHeight, int horizontalBleed = 0, int verticalBleed = 0)
: base(graphicsDevice, virtualWidth, virtualHeight)
{
_window = window;
_graphicsDevice = graphicsDevice;
window.ClientSizeChanged += OnClientSizeChanged;
HorizontalBleed = horizontalBleed;
VerticalBleed = verticalBleed;
}
/// <summary>
/// Initializes a new instance of the <see cref="BoxingViewportAdapter" />.
/// Note: If you're using DirectX please use the other constructor due to a bug in MonoGame.
/// https://github.com/mono/MonoGame/issues/4018
/// </summary>
public BoxingViewportAdapter(GameWindow window, GraphicsDevice graphicsDevice, int virtualWidth,
int virtualHeight)
: this(window, graphicsDevice, virtualWidth, virtualHeight, 0, 0)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="BoxingViewportAdapter" />.
/// Use this constructor only if you're using DirectX due to a bug in MonoGame.
/// https://github.com/mono/MonoGame/issues/4018
/// This constructor will be made obsolete and eventually removed once the bug has been fixed.
/// </summary>
public BoxingViewportAdapter(GameWindow window, GraphicsDeviceManager graphicsDeviceManager, int virtualWidth,
int virtualHeight, int horizontalBleed, int verticalBleed)
: this(
window, graphicsDeviceManager.GraphicsDevice, virtualWidth, virtualHeight, horizontalBleed,
verticalBleed)
{
_graphicsDeviceManager = graphicsDeviceManager;
}
/// <summary>
/// Initializes a new instance of the <see cref="BoxingViewportAdapter" />.
/// Use this constructor only if you're using DirectX due to a bug in MonoGame.
/// https://github.com/mono/MonoGame/issues/4018
/// This constructor will be made obsolete and eventually removed once the bug has been fixed.
/// </summary>
public BoxingViewportAdapter(GameWindow window, GraphicsDeviceManager graphicsDeviceManager, int virtualWidth,
int virtualHeight)
: this(window, graphicsDeviceManager, virtualWidth, virtualHeight, 0, 0)
public override void Dispose()
{
_window.ClientSizeChanged -= OnClientSizeChanged;
base.Dispose();
}
/// <summary>
@@ -85,45 +51,34 @@ namespace MonoGame.Extended.ViewportAdapters
private void OnClientSizeChanged(object sender, EventArgs eventArgs)
{
var viewport = GraphicsDevice.Viewport;
var clientBounds = _window.ClientBounds;
var worldScaleX = (float) viewport.Width/VirtualWidth;
var worldScaleY = (float) viewport.Height/VirtualHeight;
var worldScaleX = (float)clientBounds.Width / VirtualWidth;
var worldScaleY = (float)clientBounds.Height / VirtualHeight;
var safeScaleX = (float) viewport.Width/(VirtualWidth - HorizontalBleed);
var safeScaleY = (float) viewport.Height/(VirtualHeight - VerticalBleed);
var safeScaleX = (float)clientBounds.Width / (VirtualWidth - HorizontalBleed);
var safeScaleY = (float)clientBounds.Height / (VirtualHeight - VerticalBleed);
var worldScale = MathHelper.Max(worldScaleX, worldScaleY);
var safeScale = MathHelper.Min(safeScaleX, safeScaleY);
var scale = MathHelper.Min(worldScale, safeScale);
var width = (int) (scale*VirtualWidth + 0.5f);
var height = (int) (scale*VirtualHeight + 0.5f);
var width = (int)(scale * VirtualWidth + 0.5f);
var height = (int)(scale * VirtualHeight + 0.5f);
if ((height >= viewport.Height) && (width < viewport.Width))
if (height >= clientBounds.Height && width < clientBounds.Width)
BoxingMode = BoxingMode.Pillarbox;
else
{
if ((width >= viewport.Height) && (height < viewport.Height))
if (width >= clientBounds.Height && height <= clientBounds.Height)
BoxingMode = BoxingMode.Letterbox;
else
else
BoxingMode = BoxingMode.None;
}
var x = viewport.Width/2 - width/2;
var y = viewport.Height/2 - height/2;
var x = clientBounds.Width / 2 - width / 2;
var y = clientBounds.Height / 2 - height / 2;
GraphicsDevice.Viewport = new Viewport(x, y, width, height);
// Needed for a DirectX bug in MonoGame 3.4. Hopefully it will be fixed in future versions
// see http://gamedev.stackexchange.com/questions/68914/issue-with-monogame-resizing
if ((_graphicsDeviceManager != null) &&
((_graphicsDeviceManager.PreferredBackBufferWidth != _window.ClientBounds.Width) ||
(_graphicsDeviceManager.PreferredBackBufferHeight != _window.ClientBounds.Height)))
{
_graphicsDeviceManager.PreferredBackBufferWidth = _window.ClientBounds.Width;
_graphicsDeviceManager.PreferredBackBufferHeight = _window.ClientBounds.Height;
_graphicsDeviceManager.ApplyChanges();
}
}
public override void Reset()
@@ -1,8 +1,6 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
// ReSharper disable once CheckNamespace
namespace MonoGame.Extended.ViewportAdapters
{
public class ScalingViewportAdapter : ViewportAdapter
@@ -1,17 +1,20 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
// ReSharper disable once CheckNamespace
namespace MonoGame.Extended.ViewportAdapters
{
public abstract class ViewportAdapter
public abstract class ViewportAdapter : IDisposable
{
protected ViewportAdapter(GraphicsDevice graphicsDevice)
{
GraphicsDevice = graphicsDevice;
}
public virtual void Dispose()
{
}
public GraphicsDevice GraphicsDevice { get; }
public Viewport Viewport => GraphicsDevice.Viewport;