axiosengine/axios/ScreenSystem/ScreenManagerComponent.cs

303 lines
10 KiB
C#

using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
namespace FarseerPhysics.SamplesFramework
{
/// <summary>
/// The screen manager is a component which manages one or more GameScreen
/// instances. It maintains a stack of screens, calls their Update and Draw
/// methods at the appropriate times, and automatically routes input to the
/// topmost active screen.
/// </summary>
public class ScreenManager : DrawableGameComponent
{
private AssetCreator _assetCreator;
private ContentManager _contentManager;
private InputHelper _input;
private bool _isInitialized;
private LineBatch _lineBatch;
private List<GameScreen> _screens;
private List<GameScreen> _screensToUpdate;
private SpriteBatch _spriteBatch;
/// <summary>
/// Contains all the fonts avaliable for use.
/// </summary>
private SpriteFonts _spriteFonts;
private List<RenderTarget2D> _transitions;
/// <summary>
/// Constructs a new screen manager component.
/// </summary>
public ScreenManager(Game game)
: base(game)
{
// we must set EnabledGestures before we can query for them, but
// we don't assume the game wants to read them.
//game.Components.
TouchPanel.EnabledGestures = GestureType.None;
_contentManager = game.Content;
_contentManager.RootDirectory = "Content";
_input = new InputHelper(this);
_screens = new List<GameScreen>();
_screensToUpdate = new List<GameScreen>();
_transitions = new List<RenderTarget2D>();
}
/// <summary>
/// A default SpriteBatch shared by all the screens. This saves
/// each screen having to bother creating their own local instance.
/// </summary>
public SpriteBatch SpriteBatch
{
get { return _spriteBatch; }
}
public LineBatch LineBatch
{
get { return _lineBatch; }
}
public ContentManager Content
{
get { return _contentManager; }
}
public SpriteFonts Fonts
{
get { return _spriteFonts; }
}
public AssetCreator Assets
{
get { return _assetCreator; }
}
/// <summary>
/// Initializes the screen manager component.
/// </summary>
public override void Initialize()
{
if (!Axios.Settings.ScreenSaver)
_spriteFonts = new SpriteFonts(_contentManager);
base.Initialize();
_isInitialized = true;
}
/// <summary>
/// Load your graphics content.
/// </summary>
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
_lineBatch = new LineBatch(GraphicsDevice);
if (!Axios.Settings.ScreenSaver)
{
_assetCreator = new AssetCreator(GraphicsDevice);
_assetCreator.LoadContent(_contentManager);
_input.LoadContent();
}
// Tell each of the screens to load their content.
foreach (GameScreen screen in _screens)
{
screen.LoadContent();
}
}
/// <summary>
/// Unload your graphics content.
/// </summary>
protected override void UnloadContent()
{
// Tell each of the screens to unload their content.
foreach (GameScreen screen in _screens)
{
screen.UnloadContent();
}
}
/// <summary>
/// Allows each screen to run logic.
/// </summary>
public override void Update(GameTime gameTime)
{
// Read the keyboard and gamepad.
_input.Update(gameTime);
// Make a copy of the master screen list, to avoid confusion if
// the process of updating one screen adds or removes others.
_screensToUpdate.Clear();
if (_screens.Count == 0 || (_screens.Count == 1 && _screens[0] is BackgroundScreen))
//I'm done, exit
this.Game.Exit();
foreach (GameScreen screen in _screens)
{
_screensToUpdate.Add(screen);
}
bool otherScreenHasFocus = !Game.IsActive;
bool coveredByOtherScreen = false;
// Loop as long as there are screens waiting to be updated.
while (_screensToUpdate.Count > 0)
{
// Pop the topmost screen off the waiting list.
GameScreen screen = _screensToUpdate[_screensToUpdate.Count - 1];
_screensToUpdate.RemoveAt(_screensToUpdate.Count - 1);
// Update the screen.
screen.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
if (screen.ScreenState == ScreenState.TransitionOn ||
screen.ScreenState == ScreenState.Active)
{
// If this is the first active screen we came across,
// give it a chance to handle input.
if (!otherScreenHasFocus || screen.AlwaysHasFocus)
{
if (!otherScreenHasFocus)
{
_input.ShowCursor = screen.HasCursor;
_input.EnableVirtualStick = screen.HasVirtualStick;
otherScreenHasFocus = true;
}
screen.HandleInput(_input, gameTime);
}
// If this is an active non-popup, inform any subsequent
// screens that they are covered by it.
if (!screen.IsPopup)
{
coveredByOtherScreen = true;
}
}
}
}
/// <summary>
/// Tells each screen to draw itself.
/// </summary>
public override void Draw(GameTime gameTime)
{
int transitionCount = 0;
foreach (GameScreen screen in _screens)
{
if (screen.ScreenState == ScreenState.TransitionOn ||
screen.ScreenState == ScreenState.TransitionOff)
{
++transitionCount;
if (_transitions.Count < transitionCount)
{
PresentationParameters _pp = GraphicsDevice.PresentationParameters;
_transitions.Add(new RenderTarget2D(GraphicsDevice, _pp.BackBufferWidth, _pp.BackBufferHeight,
false,
SurfaceFormat.Color, _pp.DepthStencilFormat,
_pp.MultiSampleCount,
RenderTargetUsage.DiscardContents));
}
GraphicsDevice.SetRenderTarget(_transitions[transitionCount - 1]);
GraphicsDevice.Clear(Color.Transparent);
screen.Draw(gameTime);
GraphicsDevice.SetRenderTarget(null);
}
}
//GraphicsDevice.Clear(Color.Black);
transitionCount = 0;
foreach (GameScreen screen in _screens)
{
if (screen.ScreenState == ScreenState.Hidden)
{
continue;
}
if (screen.ScreenState == ScreenState.TransitionOn ||
screen.ScreenState == ScreenState.TransitionOff)
{
_spriteBatch.Begin(0, BlendState.AlphaBlend);
_spriteBatch.Draw(_transitions[transitionCount], Vector2.Zero, Color.White * screen.TransitionAlpha);
_spriteBatch.End();
++transitionCount;
}
else
{
screen.Draw(gameTime);
}
}
_input.Draw();
}
/// <summary>
/// Adds a new screen to the screen manager.
/// </summary>
public void AddScreen(GameScreen screen)
{
screen.ScreenManager = this;
screen.IsExiting = false;
// If we have a graphics device, tell the screen to load content.
if (_isInitialized)
{
screen.LoadContent();
}
_screens.Add(screen);
// update the TouchPanel to respond to gestures this screen is interested in
TouchPanel.EnabledGestures = screen.EnabledGestures;
}
/// <summary>
/// Removes a screen from the screen manager. You should normally
/// use GameScreen.ExitScreen instead of calling this directly, so
/// the screen can gradually transition off rather than just being
/// instantly removed.
/// </summary>
public void RemoveScreen(GameScreen screen)
{
// If we have a graphics device, tell the screen to unload content.
if (_isInitialized)
{
screen.UnloadContent();
}
_screens.Remove(screen);
_screensToUpdate.Remove(screen);
// if there is a screen still in the manager, update TouchPanel
// to respond to gestures that screen is interested in.
if (_screens.Count > 0)
{
TouchPanel.EnabledGestures = _screens[_screens.Count - 1].EnabledGestures;
}
}
/// <summary>
/// Expose an array holding all the screens. We return a copy rather
/// than the real master list, because screens should only ever be added
/// or removed using the AddScreen and RemoveScreen methods.
/// </summary>
public GameScreen[] GetScreens()
{
return _screens.ToArray();
}
}
}