#region File Description
//-----------------------------------------------------------------------------
// NetworkBusyScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
#endregion
namespace NetRumble
{
///
/// When an asynchronous network operation (for instance searching for or joining a
/// session) is in progress, we want to display some sort of busy indicator to let
/// the user know the game hasn't just locked up. We also want to make sure they
/// can't pick some other menu option before the current operation has finished.
/// This screen takes care of both requirements in a single stroke. It monitors
/// the IAsyncResult returned by an asynchronous network call, displaying a busy
/// indicator for as long as the call is still in progress. When it notices the
/// IAsyncResult has completed, it raises an event to let the game know it should
/// proceed to the next step, after which the busy screen automatically goes away.
/// Because this screen is on top of all others for as long as the asynchronous
/// operation is in progress, it automatically takes over all user input,
/// preventing any other menu entries being selected until the operation completes.
///
/// Based on a class in the Network Game State Management sample.
class NetworkBusyScreen : GameScreen
{
#region Constants
const float busyTextureScale = 0.8f;
#endregion
#region Fields
///
/// The message displayed in the screen.
///
string message;
///
/// The async result polled by the screen.
///
IAsyncResult asyncResult;
///
/// The rotating "activity" texture in the screen.
///
Texture2D busyTexture;
#endregion
#region Events
public event EventHandler OperationCompleted;
#endregion
#region Initialization
///
/// Constructs a network busy screen for the specified asynchronous operation.
///
public NetworkBusyScreen(string message, IAsyncResult asyncResult)
{
this.message = message;
this.asyncResult = asyncResult;
IsPopup = true;
TransitionOnTime = TimeSpan.FromSeconds(0.1);
TransitionOffTime = TimeSpan.FromSeconds(0.2);
}
///
/// Loads graphics content for this screen. This uses the shared ContentManager
/// provided by the Game class, so the content will remain loaded forever.
/// Whenever a subsequent NetworkBusyScreen tries to load this same content,
/// it will just get back another reference to the already loaded data.
///
public override void LoadContent()
{
ContentManager content = ScreenManager.Game.Content;
busyTexture = content.Load("Textures/chatTalking");
}
#endregion
#region Update and Draw
///
/// Updates the NetworkBusyScreen.
///
public override void Update(GameTime gameTime, bool otherScreenHasFocus,
bool coveredByOtherScreen)
{
base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
// Has our asynchronous operation completed?
if ((asyncResult != null) && asyncResult.IsCompleted)
{
// If so, raise the OperationCompleted event.
if (OperationCompleted != null)
{
OperationCompleted(this,
new OperationCompletedEventArgs(asyncResult));
}
ExitScreen();
asyncResult = null;
}
}
///
/// Draws the NetworkBusyScreen.
///
public override void Draw(GameTime gameTime)
{
SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
SpriteFont font = ScreenManager.Font;
const int hPad = 32;
const int vPad = 16;
// Center the message text in the viewport.
Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
Vector2 viewportSize = new Vector2(viewport.Width, viewport.Height);
Vector2 textSize = font.MeasureString(message);
// Add enough room to spin a texture.
Vector2 busyTextureSize = new Vector2(busyTexture.Width * busyTextureScale);
Vector2 busyTextureOrigin = new Vector2(busyTexture.Width / 2,
busyTexture.Height / 2);
textSize.X = Math.Max(textSize.X, busyTextureSize.X);
textSize.Y += busyTextureSize.Y + vPad;
Vector2 textPosition = (viewportSize - textSize) / 2;
// The background includes a border somewhat larger than the text itself.
Rectangle backgroundRectangle = new Rectangle((int)textPosition.X - hPad,
(int)textPosition.Y - vPad,
(int)textSize.X + hPad * 2,
(int)textSize.Y + vPad * 2);
// Fade the popup alpha during transitions.
Color color = new Color(255, 255, 255, TransitionAlpha);
// Draw the background rectangle.
Rectangle backgroundRectangle2 = new Rectangle(backgroundRectangle.X - 1,
backgroundRectangle.Y - 1, backgroundRectangle.Width + 2,
backgroundRectangle.Height + 2);
ScreenManager.DrawRectangle(backgroundRectangle2, new Color(128, 128, 128,
(byte)(192.0f * (float)TransitionAlpha / 255.0f)));
ScreenManager.DrawRectangle(backgroundRectangle, new Color(0, 0, 0,
(byte)(232.0f * (float)TransitionAlpha / 255.0f)));
//spriteBatch.Begin(0,BlendState.NonPremultiplied, null, null, null);
spriteBatch.Begin();
// Draw the message box text.
spriteBatch.DrawString(font, message, textPosition, color);
// Draw the spinning cat progress indicator.
float busyTextureRotation = (float)gameTime.TotalGameTime.TotalSeconds * 3;
Vector2 busyTexturePosition = new Vector2(textPosition.X + textSize.X / 2,
textPosition.Y + textSize.Y - busyTextureSize.Y / 2);
spriteBatch.Draw(busyTexture, busyTexturePosition, null, color,
busyTextureRotation, busyTextureOrigin, busyTextureScale,
SpriteEffects.None, 0);
spriteBatch.End();
}
#endregion
}
}