recrownedathenaeum/RecrownedAthenaeum/ScreenSystem/ScreenManager.cs

153 lines
5.7 KiB
C#

using Microsoft.Win32.SafeHandles;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RecrownedAthenaeum.Camera;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace RecrownedAthenaeum.ScreenSystem
{
public delegate void FirstScreenChange(Screen screen);
public class ScreenManager : IDisposable
{
bool disposed = false;
public event FirstScreenChange RequireNextScreenEvent;
private GraphicsDeviceManager graphics;
private Screen previousScreen;
private RenderTarget2D previousScreenRenderTarget;
private Screen currentScreen;
private Camera2D camera;
private bool firstScreenChangeComplete;
public Screen Screen
{
get
{
return currentScreen;
}
set
{
previousScreen = currentScreen;
currentScreen = value;
if (!Screen.Initiated)
{
Screen.Initiate(graphics.GraphicsDevice, new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight), camera);
}
if (previousScreen != null && previousScreenRenderTarget == null && previousScreen.UseRenderTargetForExitTransition)
{
previousScreenRenderTarget = new RenderTarget2D(graphics.GraphicsDevice, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight);
}
graphics.GraphicsDevice.SetRenderTarget(previousScreenRenderTarget);
graphics.GraphicsDevice.Clear(Color.Black);
Debug.WriteLine("Showing " + value.GetType().Name);
Screen.Show();
previousScreen?.Hide();
}
}
public ScreenManager(GraphicsDeviceManager graphicsDeviceManager, Camera2D camera)
{
this.graphics = graphicsDeviceManager;
this.camera = camera;
}
public void UpdateCurrentScreen(GameTime gameTime, bool assetsDone)
{
switch (Screen.State)
{
case ScreenState.EnterTransition:
if (previousScreen != null && previousScreen.UseRenderTargetForExitTransition)
{
previousScreen.UpdateTransition(gameTime.ElapsedGameTime.TotalSeconds, assetsDone);
}
Screen.UpdateTransition(gameTime.ElapsedGameTime.TotalSeconds, assetsDone);
break;
case ScreenState.ExitTransition:
if (Screen.UseRenderTargetForExitTransition || Screen.UpdateTransition(gameTime.ElapsedGameTime.TotalSeconds, assetsDone))
{
if (!firstScreenChangeComplete)
{
firstScreenChangeComplete = true;
OnFirstScreenChange(Screen);
}
if (Screen.NextScreen != null)
{
Debug.WriteLine("Changing to the next given screen.");
Screen = Screen.NextScreen;
}
else if (previousScreen != null)
{
Debug.WriteLine("Changing to previous screen.");
Screen = previousScreen;
}
else
{
throw new InvalidOperationException("No next screen provided and no previous screen to return to.");
}
}
break;
}
Screen.Update(gameTime);
}
public void DrawCurrentScreen(SpriteBatch spriteBatch)
{
graphics.GraphicsDevice.Clear(Screen.BackgroundColor);
if (Screen.State == ScreenState.EnterTransition && previousScreen != null && previousScreen.UseRenderTargetForExitTransition)
{
graphics.GraphicsDevice.SetRenderTarget(previousScreenRenderTarget);
graphics.GraphicsDevice.Clear(previousScreen.BackgroundColor);
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, camera.Matrix);
previousScreen.Draw(spriteBatch);
spriteBatch.End();
graphics.GraphicsDevice.SetRenderTarget(null);
Screen.UpdatePreviousScreenFrame(previousScreenRenderTarget);
}
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, camera.Matrix);
Screen.Draw(spriteBatch);
spriteBatch.End();
}
public void Resize(LoadingScreen loadingScreen)
{
Screen.AssetLoadStateChange(true);
Screen = loadingScreen;
previousScreenRenderTarget.Dispose();
previousScreenRenderTarget = null;
}
public void PostResize()
{
Screen.AssetLoadStateChange(false);
}
public void OnFirstScreenChange(Screen screen)
{
RequireNextScreenEvent?.Invoke(screen);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
if (disposed) return;
if (disposing)
{
previousScreenRenderTarget?.Dispose();
}
disposing = true;
}
}
}