Files
LunaLightXMG/RenderHandler.cs
2025-03-30 14:55:16 -07:00

105 lines
3.5 KiB
C#

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace LunaLightXMG
{
public class RenderHandler
{
// fields
private readonly GraphicsDevice graphicsDevice;
private readonly SpriteBatch spriteBatch;
private readonly RenderTarget2D renderTarget;
private Rectangle renderDestination;
private readonly float retroWidth;
private readonly float retroHeight;
private float zoomLevel = 1.0f;
private float zoomTarget = 1.0f;
private readonly float zoomMin = 0.50f;
private readonly float zoomNorm = 1.0f;
private readonly float zoomMax = 1.50f;
private readonly float zoomSpeed = 0.1f;
public float ZoomLevel {get => zoomLevel;}
// constructor
public RenderHandler(GraphicsDevice graphicsDevice, SpriteBatch spriteBatch, int retroWidth, int retroHeight)
{
this.graphicsDevice = graphicsDevice;
this.spriteBatch = spriteBatch;
this.retroWidth = retroWidth;
this.retroHeight = retroHeight;
renderTarget = new RenderTarget2D(graphicsDevice, retroWidth, retroHeight);
CalculateRenderDestination();
}
public void ZoomIn()
{
zoomTarget = zoomMin;
}
public void ZoomNormalize()
{
zoomTarget = zoomNorm;
}
public void ZoomOut()
{
zoomTarget = zoomMax;
}
public void UpdateZoom()
{
// interpolate to target
zoomLevel = MathHelper.Lerp(zoomLevel, zoomTarget, zoomSpeed);
// snap to target when we're close enough
if (Math.Abs(zoomLevel - zoomTarget) < 0.001f)
{
zoomLevel = zoomTarget;
}
// stay in bounds (just in case)
zoomLevel = MathHelper.Clamp(zoomLevel, zoomMin, zoomMax);
// calc new zoomed render destination
CalculateRenderDestination();
}
public void CalculateRenderDestination()
{
Point screenSize = graphicsDevice.Viewport.Bounds.Size;
// Calculate the integer scale factor
float scaleX = screenSize.X / (retroWidth * zoomLevel);
float scaleY = screenSize.Y / (retroHeight * zoomLevel);
float scale = Math.Min(scaleX, scaleY);
// Set renderDestination
renderDestination.Width = (int)(retroWidth * scale);
renderDestination.Height = (int)(retroHeight * scale);
renderDestination.X = (screenSize.X - renderDestination.Width) / 2;
renderDestination.Y = (screenSize.Y - renderDestination.Height) / 2;
}
public void BeginRenderTarget(Matrix cameraMatrix)
{
graphicsDevice.SetRenderTarget(renderTarget);
graphicsDevice.Clear(Color.Black);
spriteBatch.Begin(transformMatrix: cameraMatrix, samplerState: SamplerState.PointClamp);
}
public void EndRenderTarget()
{
spriteBatch.End();
graphicsDevice.SetRenderTarget(null);
}
public void DrawRenderTarget()
{
spriteBatch.Begin(samplerState: SamplerState.PointClamp);
spriteBatch.Draw(renderTarget, renderDestination, Color.White);
spriteBatch.End();
}
}
}