using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
// ReSharper disable once CheckNamespace
namespace MonoGame.Extended.ViewportAdapters
{
public enum BoxingMode
{
None,
Letterbox,
Pillarbox
}
public class BoxingViewportAdapter : ScalingViewportAdapter
{
private readonly GameWindow _window;
private readonly GraphicsDevice _graphicsDevice;
///
/// Initializes a new instance of the .
///
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;
}
public override void Dispose()
{
_window.ClientSizeChanged -= OnClientSizeChanged;
base.Dispose();
}
///
/// Size of horizontal bleed areas (from left and right edges) which can be safely cut off
///
public int HorizontalBleed { get; }
///
/// Size of vertical bleed areas (from top and bottom edges) which can be safely cut off
///
public int VerticalBleed { get; }
public BoxingMode BoxingMode { get; private set; }
private void OnClientSizeChanged(object sender, EventArgs eventArgs)
{
var clientBounds = _window.ClientBounds;
var worldScaleX = (float)clientBounds.Width / VirtualWidth;
var worldScaleY = (float)clientBounds.Height / VirtualHeight;
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);
if (height >= clientBounds.Height && width < clientBounds.Width)
BoxingMode = BoxingMode.Pillarbox;
else
{
if (width >= clientBounds.Height && height <= clientBounds.Height)
BoxingMode = BoxingMode.Letterbox;
else
BoxingMode = BoxingMode.None;
}
var x = clientBounds.Width / 2 - width / 2;
var y = clientBounds.Height / 2 - height / 2;
GraphicsDevice.Viewport = new Viewport(x, y, width, height);
}
public override void Reset()
{
base.Reset();
OnClientSizeChanged(this, EventArgs.Empty);
}
public override Point PointToScreen(int x, int y)
{
var viewport = GraphicsDevice.Viewport;
return base.PointToScreen(x - viewport.X, y - viewport.Y);
}
}
}