ScreenManager.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. //-----------------------------------------------------------------------------
  2. // ScreenManager.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using System;
  8. using System.Diagnostics;
  9. using System.Collections.Generic;
  10. using Microsoft.Xna.Framework;
  11. using Microsoft.Xna.Framework.Content;
  12. using Microsoft.Xna.Framework.Graphics;
  13. using Microsoft.Xna.Framework.GamerServices;
  14. namespace NetRumble
  15. {
  16. /// <summary>
  17. /// The screen manager is a component which manages one or more GameScreen
  18. /// instances. It maintains a stack of screens, calls their Update and Draw
  19. /// methods at the appropriate times, and automatically routes input to the
  20. /// topmost active screen.
  21. /// </summary>
  22. /// <remarks>
  23. /// This public class is similar to one in the GameStateManagement sample.
  24. /// </remarks>
  25. public class ScreenManager : DrawableGameComponent
  26. {
  27. List<GameScreen> screens = new List<GameScreen>();
  28. List<GameScreen> screensToUpdate = new List<GameScreen>();
  29. List<GameScreen> screensToDraw = new List<GameScreen>();
  30. InputState input = new InputState();
  31. IGraphicsDeviceService graphicsDeviceService;
  32. public SignedInGamer invited;
  33. ContentManager content;
  34. SpriteBatch spriteBatch;
  35. SpriteFont font;
  36. Texture2D blankTexture;
  37. Rectangle titleSafeArea;
  38. bool traceEnabled;
  39. /// <summary>
  40. /// Expose access to our Game instance (this is protected in the
  41. /// default GameComponent, but we want to make it public).
  42. /// </summary>
  43. new public Game Game
  44. {
  45. get { return base.Game; }
  46. }
  47. /// <summary>
  48. /// Expose access to our graphics device (this is protected in the
  49. /// default DrawableGameComponent, but we want to make it public).
  50. /// </summary>
  51. new public GraphicsDevice GraphicsDevice
  52. {
  53. get { return base.GraphicsDevice; }
  54. }
  55. /// <summary>
  56. /// A content manager used to load data that is shared between multiple
  57. /// screens. This is never unloaded, so if a screen requires a large amount
  58. /// of temporary data, it should create a local content manager instead.
  59. /// </summary>
  60. public ContentManager Content
  61. {
  62. get { return content; }
  63. }
  64. /// <summary>
  65. /// A default SpriteBatch shared by all the screens. This saves
  66. /// each screen having to bother creating their own local instance.
  67. /// </summary>
  68. public SpriteBatch SpriteBatch
  69. {
  70. get { return spriteBatch; }
  71. }
  72. /// <summary>
  73. /// A default font shared by all the screens. This saves
  74. /// each screen having to bother loading their own local copy.
  75. /// </summary>
  76. public SpriteFont Font
  77. {
  78. get { return font; }
  79. }
  80. /// <summary>
  81. /// If true, the manager prints out a list of all the screens
  82. /// each time it is updated. This can be useful for making sure
  83. /// everything is being added and removed at the right times.
  84. /// </summary>
  85. public bool TraceEnabled
  86. {
  87. get { return traceEnabled; }
  88. set { traceEnabled = value; }
  89. }
  90. /// <summary>
  91. /// The title-safe area for the menus.
  92. /// </summary>
  93. public Rectangle TitleSafeArea
  94. {
  95. get { return titleSafeArea; }
  96. }
  97. /// <summary>
  98. /// Constructs a new screen manager component.
  99. /// </summary>
  100. public ScreenManager(Game game)
  101. : base(game)
  102. {
  103. content = new ContentManager(game.Services, "Content");
  104. graphicsDeviceService = (IGraphicsDeviceService)game.Services.GetService(
  105. typeof(IGraphicsDeviceService));
  106. if (graphicsDeviceService == null)
  107. throw new InvalidOperationException("No graphics device service.");
  108. invited = null;
  109. }
  110. /// <summary>
  111. /// Load your graphics content.
  112. /// </summary>
  113. protected override void LoadContent()
  114. {
  115. // Load content belonging to the screen manager.
  116. spriteBatch = new SpriteBatch(GraphicsDevice);
  117. font = content.Load<SpriteFont>("Fonts/MenuFont");
  118. blankTexture = content.Load<Texture2D>("Textures/blank");
  119. // Tell each of the screens to load their content.
  120. foreach (GameScreen screen in screens)
  121. {
  122. screen.LoadContent();
  123. }
  124. // update the title-safe area
  125. titleSafeArea = new Rectangle(
  126. (int)Math.Floor(GraphicsDevice.Viewport.X +
  127. GraphicsDevice.Viewport.Width * 0.05f),
  128. (int)Math.Floor(GraphicsDevice.Viewport.Y +
  129. GraphicsDevice.Viewport.Height * 0.05f),
  130. (int)Math.Floor(GraphicsDevice.Viewport.Width * 0.9f),
  131. (int)Math.Floor(GraphicsDevice.Viewport.Height * 0.9f));
  132. }
  133. /// <summary>
  134. /// Unload your graphics content.
  135. /// </summary>
  136. protected override void UnloadContent()
  137. {
  138. // Unload content belonging to the screen manager.
  139. content.Unload();
  140. // Tell each of the screens to unload their content.
  141. foreach (GameScreen screen in screens)
  142. {
  143. screen.UnloadContent();
  144. }
  145. }
  146. /// <summary>
  147. /// Allows each screen to run logic.
  148. /// </summary>
  149. public override void Update(GameTime gameTime)
  150. {
  151. // Read the keyboard and gamepad.
  152. input.Update();
  153. // Make a copy of the master screen list, to avoid confusion if
  154. // the process of updating one screen adds or removes others
  155. // (or it happens on another thread)
  156. screensToUpdate.Clear();
  157. foreach (GameScreen screen in screens)
  158. screensToUpdate.Add(screen);
  159. bool otherScreenHasFocus = !Game.IsActive;
  160. bool coveredByOtherScreen = false;
  161. // Loop as long as there are screens waiting to be updated.
  162. while (screensToUpdate.Count > 0)
  163. {
  164. // Pop the topmost screen off the waiting list.
  165. GameScreen screen = screensToUpdate[screensToUpdate.Count - 1];
  166. screensToUpdate.RemoveAt(screensToUpdate.Count - 1);
  167. // Update the screen.
  168. screen.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
  169. if (screen.ScreenState == ScreenState.TransitionOn ||
  170. screen.ScreenState == ScreenState.Active)
  171. {
  172. // If this is the first active screen we came across,
  173. // give it a chance to handle input and update presence.
  174. if (!otherScreenHasFocus)
  175. {
  176. screen.HandleInput(input);
  177. screen.UpdatePresence(); // presence support
  178. otherScreenHasFocus = true;
  179. }
  180. // If this is an active non-popup, inform any subsequent
  181. // screens that they are covered by it.
  182. if (!screen.IsPopup)
  183. coveredByOtherScreen = true;
  184. }
  185. }
  186. // Print debug trace?
  187. if (traceEnabled)
  188. TraceScreens();
  189. }
  190. /// <summary>
  191. /// Prints a list of all the screens, for debugging.
  192. /// </summary>
  193. void TraceScreens()
  194. {
  195. List<string> screenNames = new List<string>();
  196. foreach (GameScreen screen in screens)
  197. screenNames.Add(screen.GetType().Name);
  198. Debug.WriteLine(string.Join(", ", screenNames.ToArray()));
  199. }
  200. /// <summary>
  201. /// Tells each screen to draw itself.
  202. /// </summary>
  203. public override void Draw(GameTime gameTime)
  204. {
  205. // Make a copy of the master screen list, to avoid confusion if
  206. // the process of drawing one screen adds or removes others
  207. // (or it happens on another thread
  208. screensToDraw.Clear();
  209. foreach (GameScreen screen in screens)
  210. screensToDraw.Add(screen);
  211. foreach (GameScreen screen in screensToDraw)
  212. {
  213. if (screen.ScreenState == ScreenState.Hidden)
  214. continue;
  215. screen.Draw(gameTime);
  216. }
  217. }
  218. /// <summary>
  219. /// Draw an empty rectangle of the given size and color.
  220. /// </summary>
  221. /// <param name="rectangle">The destination rectangle.</param>
  222. /// <param name="color">The color of the rectangle.</param>
  223. public void DrawRectangle(Rectangle rectangle, Color color)
  224. {
  225. //SpriteBatch.Begin();
  226. // We changed this to be Opaque
  227. spriteBatch.Begin(0,BlendState.Opaque, null, null, null);
  228. SpriteBatch.Draw(blankTexture, rectangle, color);
  229. SpriteBatch.End();
  230. }
  231. /// <summary>
  232. /// Adds a new screen to the screen manager.
  233. /// </summary>
  234. public void AddScreen(GameScreen screen)
  235. {
  236. screen.ScreenManager = this;
  237. // If we have a graphics device, tell the screen to load content.
  238. if ((graphicsDeviceService != null) &&
  239. (graphicsDeviceService.GraphicsDevice != null))
  240. {
  241. screen.LoadContent();
  242. }
  243. screens.Add(screen);
  244. }
  245. /// <summary>
  246. /// Removes a screen from the screen manager. You should normally
  247. /// use GameScreen.ExitScreen instead of calling this directly, so
  248. /// the screen can gradually transition off rather than just being
  249. /// instantly removed.
  250. /// </summary>
  251. public void RemoveScreen(GameScreen screen)
  252. {
  253. // If we have a graphics device, tell the screen to unload content.
  254. if ((graphicsDeviceService != null) &&
  255. (graphicsDeviceService.GraphicsDevice != null))
  256. {
  257. screen.UnloadContent();
  258. }
  259. screens.Remove(screen);
  260. screensToUpdate.Remove(screen);
  261. }
  262. /// <summary>
  263. /// Expose an array holding all the screens. We return a copy rather
  264. /// than the real master list, because screens should only ever be added
  265. /// or removed using the AddScreen and RemoveScreen methods.
  266. /// </summary>
  267. public GameScreen[] GetScreens()
  268. {
  269. return screens.ToArray();
  270. }
  271. /// <summary>
  272. /// Helper draws a translucent black fullscreen sprite, used for fading
  273. /// screens in and out, and for darkening the background behind popups.
  274. /// </summary>
  275. public void FadeBackBufferToBlack(int alpha)
  276. {
  277. Viewport viewport = GraphicsDevice.Viewport;
  278. spriteBatch.Begin();
  279. spriteBatch.Draw(blankTexture,
  280. new Rectangle(0, 0, viewport.Width, viewport.Height),
  281. new Color((byte)0, (byte)0, (byte)0, (byte)alpha));
  282. spriteBatch.End();
  283. }
  284. }
  285. }