Browse Source

Initial Check-in

Simon Jackson 8 years ago
parent
commit
b2e220f303
83 changed files with 6061 additions and 0 deletions
  1. 53 0
      .gitattributes
  2. 288 0
      .gitignore
  3. 65 0
      Content/Content.mgcb
  4. BIN
      Content/background.png
  5. BIN
      Content/blank.png
  6. 15 0
      Content/gamefont.spritefont
  7. BIN
      Content/gradient.png
  8. 15 0
      Content/menufont.spritefont
  9. 357 0
      GameStateManagement/GameScreen.cs
  10. 52 0
      GameStateManagement/GameStateManagement.csproj
  11. 49 0
      GameStateManagement/IScreenFactory.cs
  12. 96 0
      GameStateManagement/InputAction.cs
  13. 200 0
      GameStateManagement/InputState.cs
  14. 30 0
      GameStateManagement/Properties/AssemblyInfo.cs
  15. 443 0
      GameStateManagement/ScreenManager.cs
  16. 4 0
      GameStateManagement/packages.config
  17. 357 0
      GameStateManagementSample.sln
  18. 27 0
      Platforms/Android/Activity1.cs
  19. 19 0
      Platforms/Android/Assets/AboutAssets.txt
  20. 15 0
      Platforms/Android/Content/Content.mgcb
  21. 153 0
      Platforms/Android/GameStateManagementSample (Android).csproj
  22. 97 0
      Platforms/Android/GameStateManagementSample.csproj.bak
  23. 5 0
      Platforms/Android/Properties/AndroidManifest.xml
  24. 41 0
      Platforms/Android/Properties/AssemblyInfo.cs
  25. 44 0
      Platforms/Android/Resources/AboutResources.txt
  26. BIN
      Platforms/Android/Resources/Drawable/Icon.png
  27. BIN
      Platforms/Android/Resources/Drawable/Splash.png
  28. 99 0
      Platforms/Android/Resources/Resource.Designer.cs
  29. 5 0
      Platforms/Android/Resources/Values/Strings.xml
  30. 7 0
      Platforms/Android/Resources/Values/Styles.xml
  31. 173 0
      Platforms/DesktopGL/GameStateManagementSample (DesktopGL).csproj
  32. BIN
      Platforms/DesktopGL/Icon.bmp
  33. BIN
      Platforms/DesktopGL/Icon.ico
  34. 20 0
      Platforms/DesktopGL/Program.cs
  35. 36 0
      Platforms/DesktopGL/Properties/AssemblyInfo.cs
  36. 42 0
      Platforms/DesktopGL/app.manifest
  37. 127 0
      Platforms/WindowsDX/GameStateManagementSample (WindowsDX).csproj
  38. BIN
      Platforms/WindowsDX/Icon.ico
  39. 22 0
      Platforms/WindowsDX/Program.cs
  40. 36 0
      Platforms/WindowsDX/Properties/AssemblyInfo.cs
  41. 42 0
      Platforms/WindowsDX/app.manifest
  42. 8 0
      Platforms/WindowsUWP/App.xaml
  43. 134 0
      Platforms/WindowsUWP/App.xaml.cs
  44. BIN
      Platforms/WindowsUWP/Assets/LockScreenLogo.scale-200.png
  45. BIN
      Platforms/WindowsUWP/Assets/SplashScreen.scale-200.png
  46. BIN
      Platforms/WindowsUWP/Assets/Square150x150Logo.scale-200.png
  47. BIN
      Platforms/WindowsUWP/Assets/Square44x44Logo.scale-200.png
  48. BIN
      Platforms/WindowsUWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
  49. BIN
      Platforms/WindowsUWP/Assets/StoreLogo.png
  50. BIN
      Platforms/WindowsUWP/Assets/Wide310x150Logo.scale-200.png
  51. 15 0
      Platforms/WindowsUWP/Content/Content.mgcb
  52. 12 0
      Platforms/WindowsUWP/GamePage.xaml
  53. 36 0
      Platforms/WindowsUWP/GamePage.xaml.cs
  54. 207 0
      Platforms/WindowsUWP/GameStateManagementSample (UWP).csproj
  55. 48 0
      Platforms/WindowsUWP/Package.appxmanifest
  56. 29 0
      Platforms/WindowsUWP/Properties/AssemblyInfo.cs
  57. 31 0
      Platforms/WindowsUWP/Properties/Default.rd.xml
  58. 16 0
      Platforms/WindowsUWP/project.json
  59. 13 0
      Platforms/iOS/Content/Content.mgcb
  60. BIN
      Platforms/iOS/Default.png
  61. 6 0
      Platforms/iOS/Entitlements.plist
  62. 184 0
      Platforms/iOS/GameStateManagementSample (iOS).csproj
  63. BIN
      Platforms/iOS/GameThumbnail.png
  64. 23 0
      Platforms/iOS/Info.plist
  65. 31 0
      Platforms/iOS/Program.cs
  66. 34 0
      Platforms/iOS/Properties/AssemblyInfo.cs
  67. 4 0
      Platforms/iOS/packages.config
  68. 133 0
      SampleCode/Game.cs
  69. 44 0
      SampleCode/ScreenFactory.cs
  70. 114 0
      SampleCode/Screens/BackgroundScreen.cs
  71. 191 0
      SampleCode/Screens/Button.cs
  72. 266 0
      SampleCode/Screens/GameplayScreen.cs
  73. 163 0
      SampleCode/Screens/LoadingScreen.cs
  74. 98 0
      SampleCode/Screens/MainMenuScreen.cs
  75. 192 0
      SampleCode/Screens/MenuEntry.cs
  76. 267 0
      SampleCode/Screens/MenuScreen.cs
  77. 186 0
      SampleCode/Screens/MessageBoxScreen.cs
  78. 149 0
      SampleCode/Screens/OptionsMenuScreen.cs
  79. 79 0
      SampleCode/Screens/PauseMenuScreen.cs
  80. 66 0
      SampleCode/Screens/PhoneMainMenuScreen.cs
  81. 149 0
      SampleCode/Screens/PhoneMenuScreen.cs
  82. 57 0
      SampleCode/Screens/PhonePauseScreen.cs
  83. 42 0
      SampleCode/Screens/PlayerIndexEventArgs.cs

+ 53 - 0
.gitattributes

@@ -0,0 +1,53 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following 
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just comment the entries below and
+# uncomment the group further below
+###############################################################################
+
+*.sln        text eol=crlf
+*.csproj     text eol=crlf
+*.vbproj     text eol=crlf
+*.vcxproj    text eol=crlf
+*.vcproj     text eol=crlf
+*.dbproj     text eol=crlf
+*.fsproj     text eol=crlf
+*.lsproj     text eol=crlf
+*.wixproj    text eol=crlf
+*.modelproj  text eol=crlf
+*.sqlproj    text eol=crlf
+*.wmaproj    text eol=crlf
+
+*.xproj      text eol=crlf
+*.props      text eol=crlf
+*.filters    text eol=crlf
+*.vcxitems   text eol=crlf
+
+
+#*.sln       merge=binary
+#*.csproj    merge=binary
+#*.vbproj    merge=binary
+#*.vcxproj   merge=binary
+#*.vcproj    merge=binary
+#*.dbproj    merge=binary
+#*.fsproj    merge=binary
+#*.lsproj    merge=binary
+#*.wixproj   merge=binary
+#*.modelproj merge=binary
+#*.sqlproj   merge=binary
+#*.wwaproj   merge=binary
+
+#*.xproj     merge=binary
+#*.props     merge=binary
+#*.filters   merge=binary
+#*.vcxitems  merge=binary

+ 288 - 0
.gitignore

@@ -0,0 +1,288 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+**/Properties/launchSettings.json
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Typescript v1 declaration files
+typings/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs

+ 65 - 0
Content/Content.mgcb

@@ -0,0 +1,65 @@
+
+#----------------------------- Global Properties ----------------------------#
+
+/outputDir:bin
+/intermediateDir:obj
+/platform:Windows
+/config:
+/profile:Reach
+/compress:False
+
+#-------------------------------- References --------------------------------#
+
+
+#---------------------------------- Content ---------------------------------#
+
+#begin background.png
+/importer:TextureImporter
+/processor:TextureProcessor
+/processorParam:ColorKeyColor=255,0,255,255
+/processorParam:ColorKeyEnabled=True
+/processorParam:GenerateMipmaps=False
+/processorParam:PremultiplyAlpha=True
+/processorParam:ResizeToPowerOfTwo=False
+/processorParam:MakeSquare=False
+/processorParam:TextureFormat=Color
+/build:background.png
+
+#begin blank.png
+/importer:TextureImporter
+/processor:TextureProcessor
+/processorParam:ColorKeyColor=255,0,255,255
+/processorParam:ColorKeyEnabled=True
+/processorParam:GenerateMipmaps=False
+/processorParam:PremultiplyAlpha=True
+/processorParam:ResizeToPowerOfTwo=False
+/processorParam:MakeSquare=False
+/processorParam:TextureFormat=Color
+/build:blank.png
+
+#begin menufont.spritefont
+/importer:FontDescriptionImporter
+/processor:FontDescriptionProcessor
+/processorParam:PremultiplyAlpha=True
+/processorParam:TextureFormat=Compressed
+/build:menufont.spritefont
+
+#begin gamefont.spritefont
+/importer:FontDescriptionImporter
+/processor:FontDescriptionProcessor
+/processorParam:PremultiplyAlpha=True
+/processorParam:TextureFormat=Compressed
+/build:gamefont.spritefont
+
+#begin gradient.png
+/importer:TextureImporter
+/processor:TextureProcessor
+/processorParam:ColorKeyColor=255,0,255,255
+/processorParam:ColorKeyEnabled=True
+/processorParam:GenerateMipmaps=False
+/processorParam:PremultiplyAlpha=True
+/processorParam:ResizeToPowerOfTwo=False
+/processorParam:MakeSquare=False
+/processorParam:TextureFormat=Color
+/build:gradient.png
+

BIN
Content/background.png


BIN
Content/blank.png


+ 15 - 0
Content/gamefont.spritefont

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
+	<Asset Type="Graphics:FontDescription">
+		<FontName>Segoe UI</FontName>
+		<Size>32</Size>
+		<Spacing>2</Spacing>
+		<Style>Bold</Style>
+		<CharacterRegions>
+			<CharacterRegion>
+				<Start>&#32;</Start>
+				<End>&#126;</End>
+			</CharacterRegion>
+		</CharacterRegions>
+	</Asset>
+</XnaContent>

BIN
Content/gradient.png


+ 15 - 0
Content/menufont.spritefont

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
+	<Asset Type="Graphics:FontDescription">
+		<FontName>Arial</FontName>
+		<Size>20</Size>
+		<Spacing>2</Spacing>
+		<Style>Regular</Style>
+		<CharacterRegions>
+			<CharacterRegion>
+				<Start>&#32;</Start>
+				<End>&#126;</End>
+			</CharacterRegion>
+		</CharacterRegions>
+	</Asset>
+</XnaContent>

+ 357 - 0
GameStateManagement/GameScreen.cs

@@ -0,0 +1,357 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// GameScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System;
+using System.IO;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input.Touch;
+
+namespace GameStateManagement
+{
+    /// <summary>
+    /// Enum describes the screen transition state.
+    /// </summary>
+    public enum ScreenState
+    {
+        TransitionOn,
+        Active,
+        TransitionOff,
+        Hidden,
+    }
+
+
+    /// <summary>
+    /// A screen is a single layer that has update and draw logic, and which
+    /// can be combined with other layers to build up a complex menu system.
+    /// For instance the main menu, the options menu, the "are you sure you
+    /// want to quit" message box, and the main game itself are all implemented
+    /// as screens.
+    /// </summary>
+    public abstract class GameScreen
+    {
+        /// <summary>
+        /// Normally when one screen is brought up over the top of another,
+        /// the first screen will transition off to make room for the new
+        /// one. This property indicates whether the screen is only a small
+        /// popup, in which case screens underneath it do not need to bother
+        /// transitioning off.
+        /// </summary>
+        public bool IsPopup
+        {
+            get { return isPopup; }
+            protected set { isPopup = value; }
+        }
+
+        bool isPopup = false;
+
+
+        /// <summary>
+        /// Indicates how long the screen takes to
+        /// transition on when it is activated.
+        /// </summary>
+        public TimeSpan TransitionOnTime
+        {
+            get { return transitionOnTime; }
+            protected set { transitionOnTime = value; }
+        }
+
+        TimeSpan transitionOnTime = TimeSpan.Zero;
+
+
+        /// <summary>
+        /// Indicates how long the screen takes to
+        /// transition off when it is deactivated.
+        /// </summary>
+        public TimeSpan TransitionOffTime
+        {
+            get { return transitionOffTime; }
+            protected set { transitionOffTime = value; }
+        }
+
+        TimeSpan transitionOffTime = TimeSpan.Zero;
+
+
+        /// <summary>
+        /// Gets the current position of the screen transition, ranging
+        /// from zero (fully active, no transition) to one (transitioned
+        /// fully off to nothing).
+        /// </summary>
+        public float TransitionPosition
+        {
+            get { return transitionPosition; }
+            protected set { transitionPosition = value; }
+        }
+
+        float transitionPosition = 1;
+
+
+        /// <summary>
+        /// Gets the current alpha of the screen transition, ranging
+        /// from 1 (fully active, no transition) to 0 (transitioned
+        /// fully off to nothing).
+        /// </summary>
+        public float TransitionAlpha
+        {
+            get { return 1f - TransitionPosition; }
+        }
+
+
+        /// <summary>
+        /// Gets the current screen transition state.
+        /// </summary>
+        public ScreenState ScreenState
+        {
+            get { return screenState; }
+            protected set { screenState = value; }
+        }
+
+        ScreenState screenState = ScreenState.TransitionOn;
+
+
+        /// <summary>
+        /// There are two possible reasons why a screen might be transitioning
+        /// off. It could be temporarily going away to make room for another
+        /// screen that is on top of it, or it could be going away for good.
+        /// This property indicates whether the screen is exiting for real:
+        /// if set, the screen will automatically remove itself as soon as the
+        /// transition finishes.
+        /// </summary>
+        public bool IsExiting
+        {
+            get { return isExiting; }
+            protected internal set { isExiting = value; }
+        }
+
+        bool isExiting = false;
+
+
+        /// <summary>
+        /// Checks whether this screen is active and can respond to user input.
+        /// </summary>
+        public bool IsActive
+        {
+            get
+            {
+                return !otherScreenHasFocus &&
+                       (screenState == ScreenState.TransitionOn ||
+                        screenState == ScreenState.Active);
+            }
+        }
+
+        bool otherScreenHasFocus;
+
+
+        /// <summary>
+        /// Gets the manager that this screen belongs to.
+        /// </summary>
+        public ScreenManager ScreenManager
+        {
+            get { return screenManager; }
+            internal set { screenManager = value; }
+        }
+
+        ScreenManager screenManager;
+
+
+        /// <summary>
+        /// Gets the index of the player who is currently controlling this screen,
+        /// or null if it is accepting input from any player. This is used to lock
+        /// the game to a specific player profile. The main menu responds to input
+        /// from any connected gamepad, but whichever player makes a selection from
+        /// this menu is given control over all subsequent screens, so other gamepads
+        /// are inactive until the controlling player returns to the main menu.
+        /// </summary>
+        public PlayerIndex? ControllingPlayer
+        {
+            get { return controllingPlayer; }
+            internal set { controllingPlayer = value; }
+        }
+
+        PlayerIndex? controllingPlayer;
+
+
+        /// <summary>
+        /// Gets the gestures the screen is interested in. Screens should be as specific
+        /// as possible with gestures to increase the accuracy of the gesture engine.
+        /// For example, most menus only need Tap or perhaps Tap and VerticalDrag to operate.
+        /// These gestures are handled by the ScreenManager when screens change and
+        /// all gestures are placed in the InputState passed to the HandleInput method.
+        /// </summary>
+        public GestureType EnabledGestures
+        {
+            get { return enabledGestures; }
+            protected set
+            {
+                enabledGestures = value;
+
+                // the screen manager handles this during screen changes, but
+                // if this screen is active and the gesture types are changing,
+                // we have to update the TouchPanel ourself.
+                if (ScreenState == ScreenState.Active)
+                {
+                    TouchPanel.EnabledGestures = value;
+                }
+            }
+        }
+
+        GestureType enabledGestures = GestureType.None;
+
+        /// <summary>
+        /// Gets whether or not this screen is serializable. If this is true,
+        /// the screen will be recorded into the screen manager's state and
+        /// its Serialize and Deserialize methods will be called as appropriate.
+        /// If this is false, the screen will be ignored during serialization.
+        /// By default, all screens are assumed to be serializable.
+        /// </summary>
+        public bool IsSerializable
+        {
+            get { return isSerializable; }
+            protected set { isSerializable = value; }
+        }
+
+        bool isSerializable = true;
+        
+        
+        /// <summary>
+        /// Activates the screen. Called when the screen is added to the screen manager or if the game resumes
+        /// from being paused or tombstoned.
+        /// </summary>
+        /// <param name="instancePreserved">
+        /// True if the game was preserved during deactivation, false if the screen is just being added or if the game was tombstoned.
+        /// On Xbox and Windows this will always be false.
+        /// </param>
+        public virtual void Activate(bool instancePreserved) { }
+
+        
+        /// <summary>
+        /// Deactivates the screen. Called when the game is being deactivated due to pausing or tombstoning.
+        /// </summary>
+        public virtual void Deactivate() { }
+
+
+        /// <summary>
+        /// Unload content for the screen. Called when the screen is removed from the screen manager.
+        /// </summary>
+        public virtual void Unload() { }
+
+
+        /// <summary>
+        /// Allows the screen to run logic, such as updating the transition position.
+        /// Unlike HandleInput, this method is called regardless of whether the screen
+        /// is active, hidden, or in the middle of a transition.
+        /// </summary>
+        public virtual void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
+        {
+            this.otherScreenHasFocus = otherScreenHasFocus;
+
+            if (isExiting)
+            {
+                // If the screen is going away to die, it should transition off.
+                screenState = ScreenState.TransitionOff;
+
+                if (!UpdateTransition(gameTime, transitionOffTime, 1))
+                {
+                    // When the transition finishes, remove the screen.
+                    ScreenManager.RemoveScreen(this);
+                }
+            }
+            else if (coveredByOtherScreen)
+            {
+                // If the screen is covered by another, it should transition off.
+                if (UpdateTransition(gameTime, transitionOffTime, 1))
+                {
+                    // Still busy transitioning.
+                    screenState = ScreenState.TransitionOff;
+                }
+                else
+                {
+                    // Transition finished!
+                    screenState = ScreenState.Hidden;
+                }
+            }
+            else
+            {
+                // Otherwise the screen should transition on and become active.
+                if (UpdateTransition(gameTime, transitionOnTime, -1))
+                {
+                    // Still busy transitioning.
+                    screenState = ScreenState.TransitionOn;
+                }
+                else
+                {
+                    // Transition finished!
+                    screenState = ScreenState.Active;
+                }
+            }
+        }
+
+
+        /// <summary>
+        /// Helper for updating the screen transition position.
+        /// </summary>
+        bool UpdateTransition(GameTime gameTime, TimeSpan time, int direction)
+        {
+            // How much should we move by?
+            float transitionDelta;
+
+            if (time == TimeSpan.Zero)
+                transitionDelta = 1;
+            else
+                transitionDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / time.TotalMilliseconds);
+
+            // Update the transition position.
+            transitionPosition += transitionDelta * direction;
+
+            // Did we reach the end of the transition?
+            if (((direction < 0) && (transitionPosition <= 0)) ||
+                ((direction > 0) && (transitionPosition >= 1)))
+            {
+                transitionPosition = MathHelper.Clamp(transitionPosition, 0, 1);
+                return false;
+            }
+
+            // Otherwise we are still busy transitioning.
+            return true;
+        }
+
+
+        /// <summary>
+        /// Allows the screen to handle user input. Unlike Update, this method
+        /// is only called when the screen is active, and not when some other
+        /// screen has taken the focus.
+        /// </summary>
+        public virtual void HandleInput(GameTime gameTime, InputState input) { }
+
+
+        /// <summary>
+        /// This is called when the screen should draw itself.
+        /// </summary>
+        public virtual void Draw(GameTime gameTime) { }
+
+
+        /// <summary>
+        /// Tells the screen to go away. Unlike ScreenManager.RemoveScreen, which
+        /// instantly kills the screen, this method respects the transition timings
+        /// and will give the screen a chance to gradually transition off.
+        /// </summary>
+        public void ExitScreen()
+        {
+            if (TransitionOffTime == TimeSpan.Zero)
+            {
+                // If the screen has a zero transition time, remove it immediately.
+                ScreenManager.RemoveScreen(this);
+            }
+            else
+            {
+                // Otherwise flag that it should transition off and then exit.
+                isExiting = true;
+            }
+        }
+    }
+}

+ 52 - 0
GameStateManagement/GameStateManagement.csproj

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{08CF175B-0057-47AF-8C8D-406010A53895}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>GameStateManagement</RootNamespace>
+    <AssemblyName>GameStateManagement</AssemblyName>
+    <DefaultLanguage>en-US</DefaultLanguage>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="GameScreen.cs" />
+    <Compile Include="InputAction.cs" />
+    <Compile Include="InputState.cs" />
+    <Compile Include="IScreenFactory.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="ScreenManager.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="MonoGame.Framework, Version=3.6.0.1625, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\MonoGame.Framework.Portable.3.6.0.1625\lib\portable-net45+win8+wpa81\MonoGame.Framework.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+</Project>

+ 49 - 0
GameStateManagement/IScreenFactory.cs

@@ -0,0 +1,49 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// IScreenFactory.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System;
+
+namespace GameStateManagement
+{
+    /// <summary>
+    /// Defines an object that can create a screen when given its type.
+    /// 
+    /// The ScreenManager attempts to handle tombstoning on Windows Phone by creating an XML
+    /// document that has a list of the screens currently in the manager. When the game is
+    /// reactivated, the ScreenManager needs to create instances of those screens. However
+    /// since there is no restriction that a particular GameScreen subclass has a parameterless
+    /// constructor, there is no way the ScreenManager alone could create those instances.
+    /// 
+    /// IScreenFactory fills this gap by providing an interface the game should implement to
+    /// act as a translation from type to instance. The ScreenManager locates the IScreenFactory
+    /// from the Game.Services collection and passes each screen type to the factory, expecting
+    /// to get the correct GameScreen out.
+    /// 
+    /// If your game screens all have parameterless constructors, the minimal implementation of
+    /// this interface would look like this:
+    /// 
+    /// return Activator.CreateInstance(screenType) as GameScreen;
+    /// 
+    /// If you have screens with constructors that take arguments, you will need to ensure that
+    /// you can read these arguments from storage or generate new ones, then construct the screen
+    /// based on the type.
+    /// 
+    /// The ScreenFactory type in the sample game has the minimal implementation along with some
+    /// extra comments showing a potentially more complex example of how to implement IScreenFactory.
+    /// </summary>
+    public interface IScreenFactory
+    {
+        /// <summary>
+        /// Creates a GameScreen from the given type.
+        /// </summary>
+        /// <param name="screenType">The type of screen to create.</param>
+        /// <returns>The newly created screen.</returns>
+        GameScreen CreateScreen(Type screenType);
+    }
+}

+ 96 - 0
GameStateManagement/InputAction.cs

@@ -0,0 +1,96 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// InputAction.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+
+namespace GameStateManagement
+{
+    /// <summary>
+    /// Defines an action that is designated by some set of buttons and/or keys.
+    /// 
+    /// The way actions work is that you define a set of buttons and keys that trigger the action. You can
+    /// then evaluate the action against an InputState which will test to see if any of the buttons or keys
+    /// are pressed by a player. You can also set a flag that indicates if the action only occurs once when
+    /// the buttons/keys are first pressed or whether the action should occur each frame.
+    /// 
+    /// Using this InputAction class means that you can configure new actions based on keys and buttons
+    /// without having to directly modify the InputState type. This means more customization by your games
+    /// without having to change the core classes of Game State Management.
+    /// </summary>
+    public class InputAction
+    {
+        private readonly Buttons[] buttons;
+        private readonly Keys[] keys;
+        private readonly bool newPressOnly;
+
+        // These delegate types map to the methods on InputState. We use these to simplify the evalute method
+        // by allowing us to map the appropriate delegates and invoke them, rather than having two separate code paths.
+        private delegate bool ButtonPress(Buttons button, PlayerIndex? controllingPlayer, out PlayerIndex player);
+        private delegate bool KeyPress(Keys key, PlayerIndex? controllingPlayer, out PlayerIndex player);
+
+        /// <summary>
+        /// Initializes a new InputAction.
+        /// </summary>
+        /// <param name="buttons">An array of buttons that can trigger the action.</param>
+        /// <param name="keys">An array of keys that can trigger the action.</param>
+        /// <param name="newPressOnly">Whether the action only occurs on the first press of one of the buttons/keys, 
+        /// false if it occurs each frame one of the buttons/keys is down.</param>
+        public InputAction(Buttons[] buttons, Keys[] keys, bool newPressOnly)
+        {
+            // Store the buttons and keys. If the arrays are null, we create a 0 length array so we don't
+            // have to do null checks in the Evaluate method
+            this.buttons = buttons != null ? buttons.Clone() as Buttons[] : new Buttons[0];
+            this.keys = keys != null ? keys.Clone() as Keys[] : new Keys[0];
+
+            this.newPressOnly = newPressOnly;
+        }
+
+        /// <summary>
+        /// Evaluates the action against a given InputState.
+        /// </summary>
+        /// <param name="state">The InputState to test for the action.</param>
+        /// <param name="controllingPlayer">The player to test, or null to allow any player.</param>
+        /// <param name="player">If controllingPlayer is null, this is the player that performed the action.</param>
+        /// <returns>True if the action occurred, false otherwise.</returns>
+        public bool Evaluate(InputState state, PlayerIndex? controllingPlayer, out PlayerIndex player)
+        {
+            // Figure out which delegate methods to map from the state which takes care of our "newPressOnly" logic
+            ButtonPress buttonTest;
+            KeyPress keyTest;
+            if (newPressOnly)
+            {
+                buttonTest = state.IsNewButtonPress;
+                keyTest = state.IsNewKeyPress;
+            }
+            else
+            {
+                buttonTest = state.IsButtonPressed;
+                keyTest = state.IsKeyPressed;
+            }
+
+            // Now we simply need to invoke the appropriate methods for each button and key in our collections
+            foreach (Buttons button in buttons)
+            {
+                if (buttonTest(button, controllingPlayer, out player))
+                    return true;
+            }
+            foreach (Keys key in keys)
+            {
+                if (keyTest(key, controllingPlayer, out player))
+                    return true;
+            }
+
+            // If we got here, the action is not matched
+            player = PlayerIndex.One;
+            return false;
+        }
+    }
+}

+ 200 - 0
GameStateManagement/InputState.cs

@@ -0,0 +1,200 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// InputState.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+using Microsoft.Xna.Framework.Input.Touch;
+
+namespace GameStateManagement
+{
+    /// <summary>
+    /// Helper for reading input from keyboard, gamepad, and touch input. This class 
+    /// tracks both the current and previous state of the input devices, and implements 
+    /// query methods for high level input actions such as "move up through the menu"
+    /// or "pause the game".
+    /// </summary>
+    public class InputState
+    {
+        public const int MaxInputs = 4;
+
+        public readonly KeyboardState[] CurrentKeyboardStates;
+        public readonly GamePadState[] CurrentGamePadStates;
+
+        public readonly KeyboardState[] LastKeyboardStates;
+        public readonly GamePadState[] LastGamePadStates;
+
+        public readonly bool[] GamePadWasConnected;
+
+        public TouchCollection TouchState;
+
+        public readonly List<GestureSample> Gestures = new List<GestureSample>();
+        
+
+        /// <summary>
+        /// Constructs a new input state.
+        /// </summary>
+        public InputState()
+        {
+            CurrentKeyboardStates = new KeyboardState[MaxInputs];
+            CurrentGamePadStates = new GamePadState[MaxInputs];
+
+            LastKeyboardStates = new KeyboardState[MaxInputs];
+            LastGamePadStates = new GamePadState[MaxInputs];
+
+            GamePadWasConnected = new bool[MaxInputs];
+        }
+
+        /// <summary>
+        /// Reads the latest state user input.
+        /// </summary>
+        public void Update()
+        {
+            for (int i = 0; i < MaxInputs; i++)
+            {
+                LastKeyboardStates[i] = CurrentKeyboardStates[i];
+                LastGamePadStates[i] = CurrentGamePadStates[i];
+
+                CurrentKeyboardStates[i] = Keyboard.GetState((PlayerIndex)i);
+                CurrentGamePadStates[i] = GamePad.GetState((PlayerIndex)i);
+
+                // Keep track of whether a gamepad has ever been
+                // connected, so we can detect if it is unplugged.
+                if (CurrentGamePadStates[i].IsConnected)
+                {
+                    GamePadWasConnected[i] = true;
+                }
+            }
+
+            // Get the raw touch state from the TouchPanel
+            TouchState = TouchPanel.GetState();
+
+            // Read in any detected gestures into our list for the screens to later process
+            Gestures.Clear();
+            while (TouchPanel.IsGestureAvailable)
+            {
+                Gestures.Add(TouchPanel.ReadGesture());
+            }
+        }
+
+
+        /// <summary>
+        /// Helper for checking if a key was pressed during this update. The
+        /// controllingPlayer parameter specifies which player to read input for.
+        /// If this is null, it will accept input from any player. When a keypress
+        /// is detected, the output playerIndex reports which player pressed it.
+        /// </summary>
+        public bool IsKeyPressed(Keys key, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
+        {
+            if (controllingPlayer.HasValue)
+            {
+                // Read input from the specified player.
+                playerIndex = controllingPlayer.Value;
+
+                int i = (int)playerIndex;
+
+                return CurrentKeyboardStates[i].IsKeyDown(key);
+            }
+            else
+            {
+                // Accept input from any player.
+                return (IsKeyPressed(key, PlayerIndex.One, out playerIndex) ||
+                        IsKeyPressed(key, PlayerIndex.Two, out playerIndex) ||
+                        IsKeyPressed(key, PlayerIndex.Three, out playerIndex) ||
+                        IsKeyPressed(key, PlayerIndex.Four, out playerIndex));
+            }
+        }
+
+
+        /// <summary>
+        /// Helper for checking if a button was pressed during this update.
+        /// The controllingPlayer parameter specifies which player to read input for.
+        /// If this is null, it will accept input from any player. When a button press
+        /// is detected, the output playerIndex reports which player pressed it.
+        /// </summary>
+        public bool IsButtonPressed(Buttons button, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
+        {
+            if (controllingPlayer.HasValue)
+            {
+                // Read input from the specified player.
+                playerIndex = controllingPlayer.Value;
+
+                int i = (int)playerIndex;
+
+                return CurrentGamePadStates[i].IsButtonDown(button);
+            }
+            else
+            {
+                // Accept input from any player.
+                return (IsButtonPressed(button, PlayerIndex.One, out playerIndex) ||
+                        IsButtonPressed(button, PlayerIndex.Two, out playerIndex) ||
+                        IsButtonPressed(button, PlayerIndex.Three, out playerIndex) ||
+                        IsButtonPressed(button, PlayerIndex.Four, out playerIndex));
+            }
+        }
+
+
+        /// <summary>
+        /// Helper for checking if a key was newly pressed during this update. The
+        /// controllingPlayer parameter specifies which player to read input for.
+        /// If this is null, it will accept input from any player. When a keypress
+        /// is detected, the output playerIndex reports which player pressed it.
+        /// </summary>
+        public bool IsNewKeyPress(Keys key, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
+        {
+            if (controllingPlayer.HasValue)
+            {
+                // Read input from the specified player.
+                playerIndex = controllingPlayer.Value;
+
+                int i = (int)playerIndex;
+
+                return (CurrentKeyboardStates[i].IsKeyDown(key) &&
+                        LastKeyboardStates[i].IsKeyUp(key));
+            }
+            else
+            {
+                // Accept input from any player.
+                return (IsNewKeyPress(key, PlayerIndex.One, out playerIndex) ||
+                        IsNewKeyPress(key, PlayerIndex.Two, out playerIndex) ||
+                        IsNewKeyPress(key, PlayerIndex.Three, out playerIndex) ||
+                        IsNewKeyPress(key, PlayerIndex.Four, out playerIndex));
+            }
+        }
+
+
+        /// <summary>
+        /// Helper for checking if a button was newly pressed during this update.
+        /// The controllingPlayer parameter specifies which player to read input for.
+        /// If this is null, it will accept input from any player. When a button press
+        /// is detected, the output playerIndex reports which player pressed it.
+        /// </summary>
+        public bool IsNewButtonPress(Buttons button, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
+        {
+            if (controllingPlayer.HasValue)
+            {
+                // Read input from the specified player.
+                playerIndex = controllingPlayer.Value;
+
+                int i = (int)playerIndex;
+
+                return (CurrentGamePadStates[i].IsButtonDown(button) &&
+                        LastGamePadStates[i].IsButtonUp(button));
+            }
+            else
+            {
+                // Accept input from any player.
+                return (IsNewButtonPress(button, PlayerIndex.One, out playerIndex) ||
+                        IsNewButtonPress(button, PlayerIndex.Two, out playerIndex) ||
+                        IsNewButtonPress(button, PlayerIndex.Three, out playerIndex) ||
+                        IsNewButtonPress(button, PlayerIndex.Four, out playerIndex));
+            }
+        }
+    }
+}

+ 30 - 0
GameStateManagement/Properties/AssemblyInfo.cs

@@ -0,0 +1,30 @@
+using System.Resources;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GameStateManagement")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("GameStateManagement")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 443 - 0
GameStateManagement/ScreenManager.cs

@@ -0,0 +1,443 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// ScreenManager.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input.Touch;
+using System.Collections.Generic;
+using System.Diagnostics;
+#endregion
+
+namespace GameStateManagement
+{
+    /// <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
+    {
+        #region Fields
+
+        private const string StateFilename = "ScreenManagerState.xml";
+
+        List<GameScreen> screens = new List<GameScreen>();
+        List<GameScreen> tempScreensList = new List<GameScreen>();
+
+        InputState input = new InputState();
+
+        SpriteBatch spriteBatch;
+        SpriteFont font;
+        Texture2D blankTexture;
+
+        bool isInitialized;
+
+        bool traceEnabled;
+
+        #endregion
+
+        #region Properties
+
+
+        /// <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; }
+        }
+
+
+        /// <summary>
+        /// A default font shared by all the screens. This saves
+        /// each screen having to bother loading their own local copy.
+        /// </summary>
+        public SpriteFont Font
+        {
+            get { return font; }
+        }
+
+
+        /// <summary>
+        /// If true, the manager prints out a list of all the screens
+        /// each time it is updated. This can be useful for making sure
+        /// everything is being added and removed at the right times.
+        /// </summary>
+        public bool TraceEnabled
+        {
+            get { return traceEnabled; }
+            set { traceEnabled = value; }
+        }
+
+
+        /// <summary>
+        /// Gets a blank texture that can be used by the screens.
+        /// </summary>
+        public Texture2D BlankTexture
+        {
+            get { return blankTexture; }
+        }
+
+
+        #endregion
+
+        #region Initialization
+
+
+        /// <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.
+            TouchPanel.EnabledGestures = GestureType.None;
+        }
+
+
+        /// <summary>
+        /// Initializes the screen manager component.
+        /// </summary>
+        public override void Initialize()
+        {
+            base.Initialize();
+
+            isInitialized = true;
+        }
+
+
+        /// <summary>
+        /// Load your graphics content.
+        /// </summary>
+        protected override void LoadContent()
+        {
+            // Load content belonging to the screen manager.
+            ContentManager content = Game.Content;
+
+            spriteBatch = new SpriteBatch(GraphicsDevice);
+            font = content.Load<SpriteFont>("menufont");
+            blankTexture = content.Load<Texture2D>("blank");
+
+            // Tell each of the screens to load their content.
+            foreach (GameScreen screen in screens)
+            {
+                screen.Activate(false);
+            }
+        }
+
+
+        /// <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.Unload();
+            }
+        }
+
+
+        #endregion
+
+        #region Update and Draw
+
+
+        /// <summary>
+        /// Allows each screen to run logic.
+        /// </summary>
+        public override void Update(GameTime gameTime)
+        {
+            // Read the keyboard and gamepad.
+            input.Update();
+
+            // Make a copy of the master screen list, to avoid confusion if
+            // the process of updating one screen adds or removes others.
+            tempScreensList.Clear();
+
+            foreach (GameScreen screen in screens)
+                tempScreensList.Add(screen);
+
+            bool otherScreenHasFocus = !Game.IsActive;
+            bool coveredByOtherScreen = false;
+
+            // Loop as long as there are screens waiting to be updated.
+            while (tempScreensList.Count > 0)
+            {
+                // Pop the topmost screen off the waiting list.
+                GameScreen screen = tempScreensList[tempScreensList.Count - 1];
+
+                tempScreensList.RemoveAt(tempScreensList.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.HandleInput(gameTime, input);
+
+                        otherScreenHasFocus = true;
+                    }
+
+                    // If this is an active non-popup, inform any subsequent
+                    // screens that they are covered by it.
+                    if (!screen.IsPopup)
+                        coveredByOtherScreen = true;
+                }
+            }
+
+            // Print debug trace?
+            if (traceEnabled)
+                TraceScreens();
+        }
+
+
+        /// <summary>
+        /// Prints a list of all the screens, for debugging.
+        /// </summary>
+        void TraceScreens()
+        {
+            List<string> screenNames = new List<string>();
+
+            foreach (GameScreen screen in screens)
+                screenNames.Add(screen.GetType().Name);
+
+            Debug.WriteLine(string.Join(", ", screenNames.ToArray()));
+        }
+
+
+        /// <summary>
+        /// Tells each screen to draw itself.
+        /// </summary>
+        public override void Draw(GameTime gameTime)
+        {
+            foreach (GameScreen screen in screens)
+            {
+                if (screen.ScreenState == ScreenState.Hidden)
+                    continue;
+
+                screen.Draw(gameTime);
+            }
+        }
+
+
+        #endregion
+
+        #region Public Methods
+
+
+        /// <summary>
+        /// Adds a new screen to the screen manager.
+        /// </summary>
+        public void AddScreen(GameScreen screen, PlayerIndex? controllingPlayer)
+        {
+            screen.ControllingPlayer = controllingPlayer;
+            screen.ScreenManager = this;
+            screen.IsExiting = false;
+
+            // If we have a graphics device, tell the screen to load content.
+            if (isInitialized)
+            {
+                screen.Activate(false);
+            }
+
+            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.Unload();
+            }
+
+            screens.Remove(screen);
+            tempScreensList.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();
+        }
+
+
+        /// <summary>
+        /// Helper draws a translucent black fullscreen sprite, used for fading
+        /// screens in and out, and for darkening the background behind popups.
+        /// </summary>
+        public void FadeBackBufferToBlack(float alpha)
+        {
+            spriteBatch.Begin();
+            spriteBatch.Draw(blankTexture, GraphicsDevice.Viewport.Bounds, Color.Black * alpha);
+            spriteBatch.End();
+        }
+
+        /// <summary>
+        /// Informs the screen manager to serialize its state to disk.
+        /// </summary>
+        public void Deactivate()
+        {
+#if !WINDOWS_PHONE
+            return;
+#else
+            // Open up isolated storage
+            using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
+            {
+                // Create an XML document to hold the list of screen types currently in the stack
+                XDocument doc = new XDocument();
+                XElement root = new XElement("ScreenManager");
+                doc.Add(root);
+
+                // Make a copy of the master screen list, to avoid confusion if
+                // the process of deactivating one screen adds or removes others.
+                tempScreensList.Clear();
+                foreach (GameScreen screen in screens)
+                    tempScreensList.Add(screen);
+
+                // Iterate the screens to store in our XML file and deactivate them
+                foreach (GameScreen screen in tempScreensList)
+                {
+                    // Only add the screen to our XML if it is serializable
+                    if (screen.IsSerializable)
+                    {
+                        // We store the screen's controlling player so we can rehydrate that value
+                        string playerValue = screen.ControllingPlayer.HasValue
+                            ? screen.ControllingPlayer.Value.ToString()
+                            : "";
+
+                        root.Add(new XElement(
+                            "GameScreen",
+                            new XAttribute("Type", screen.GetType().AssemblyQualifiedName),
+                            new XAttribute("ControllingPlayer", playerValue)));
+                    }
+
+                    // Deactivate the screen regardless of whether we serialized it
+                    screen.Deactivate();
+                }
+
+                // Save the document
+                using (IsolatedStorageFileStream stream = storage.CreateFile(StateFilename))
+                {
+                    doc.Save(stream);
+                }
+            }
+#endif
+        }
+
+        public bool Activate(bool instancePreserved)
+        {
+#if !WINDOWS_PHONE
+            return false;
+#else
+            // If the game instance was preserved, the game wasn't dehydrated so our screens still exist.
+            // We just need to activate them and we're ready to go.
+            if (instancePreserved)
+            {
+                // Make a copy of the master screen list, to avoid confusion if
+                // the process of activating one screen adds or removes others.
+                tempScreensList.Clear();
+
+                foreach (GameScreen screen in screens)
+                    tempScreensList.Add(screen);
+
+                foreach (GameScreen screen in tempScreensList)
+                    screen.Activate(true);
+            }
+
+            // Otherwise we need to refer to our saved file and reconstruct the screens that were present
+            // when the game was deactivated.
+            else
+            {
+                // Try to get the screen factory from the services, which is required to recreate the screens
+                IScreenFactory screenFactory = Game.Services.GetService(typeof(IScreenFactory)) as IScreenFactory;
+                if (screenFactory == null)
+                {
+                    throw new InvalidOperationException(
+                        "Game.Services must contain an IScreenFactory in order to activate the ScreenManager.");
+                }
+
+                // Open up isolated storage
+                using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    // Check for the file; if it doesn't exist we can't restore state
+                    if (!storage.FileExists(StateFilename))
+                        return false;
+
+                    // Read the state file so we can build up our screens
+                    using (IsolatedStorageFileStream stream = storage.OpenFile(StateFilename, FileMode.Open))
+                    {
+                        XDocument doc = XDocument.Load(stream);
+
+                        // Iterate the document to recreate the screen stack
+                        foreach (XElement screenElem in doc.Root.Elements("GameScreen"))
+                        {
+                            // Use the factory to create the screen
+                            Type screenType = Type.GetType(screenElem.Attribute("Type").Value);
+                            GameScreen screen = screenFactory.CreateScreen(screenType);
+
+                            // Rehydrate the controlling player for the screen
+                            PlayerIndex? controllingPlayer = screenElem.Attribute("ControllingPlayer").Value != ""
+                                ? (PlayerIndex)Enum.Parse(typeof(PlayerIndex), screenElem.Attribute("ControllingPlayer").Value, true)
+                                : (PlayerIndex?)null;
+                            screen.ControllingPlayer = controllingPlayer;
+
+                            // Add the screen to the screens list and activate the screen
+                            screen.ScreenManager = this;
+                            screens.Add(screen);
+                            screen.Activate(false);
+
+                            // update the TouchPanel to respond to gestures this screen is interested in
+                            TouchPanel.EnabledGestures = screen.EnabledGestures;
+                        }
+                    }
+                }
+            }
+
+            return true;
+#endif
+        }
+
+        #endregion
+    }
+}

+ 4 - 0
GameStateManagement/packages.config

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="MonoGame.Framework.Portable" version="3.6.0.1625" targetFramework="portable45-net45+win8" />
+</packages>

+ 357 - 0
GameStateManagementSample.sln

@@ -0,0 +1,357 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26228.9
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameStateManagement", "GameStateManagement\GameStateManagement.csproj", "{08CF175B-0057-47AF-8C8D-406010A53895}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{B7157C98-57CE-457E-A45C-9D1D746A7B93}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameStateManagementSample (DesktopGL)", "Platforms\DesktopGL\GameStateManagementSample (DesktopGL).csproj", "{055FEDD0-AB52-45CE-A74D-48C009E4DB73}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameStateManagementSample (WindowsDX)", "Platforms\WindowsDX\GameStateManagementSample (WindowsDX).csproj", "{360266C3-DF94-4A96-A1C9-915D97D6549F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameStateManagementSample (UWP)", "Platforms\WindowsUWP\GameStateManagementSample (UWP).csproj", "{98E44B20-48E2-4B36-9A87-D626E2C598BB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameStateManagementSample (Android)", "Platforms\Android\GameStateManagementSample (Android).csproj", "{39138599-48BD-4DCF-83AF-78DBB4C23277}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameStateManagementSample (iOS)", "Platforms\iOS\GameStateManagementSample (iOS).csproj", "{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
+		Ad-Hoc|ARM = Ad-Hoc|ARM
+		Ad-Hoc|iPhone = Ad-Hoc|iPhone
+		Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator
+		Ad-Hoc|x64 = Ad-Hoc|x64
+		Ad-Hoc|x86 = Ad-Hoc|x86
+		AppStore|Any CPU = AppStore|Any CPU
+		AppStore|ARM = AppStore|ARM
+		AppStore|iPhone = AppStore|iPhone
+		AppStore|iPhoneSimulator = AppStore|iPhoneSimulator
+		AppStore|x64 = AppStore|x64
+		AppStore|x86 = AppStore|x86
+		Debug|Any CPU = Debug|Any CPU
+		Debug|ARM = Debug|ARM
+		Debug|iPhone = Debug|iPhone
+		Debug|iPhoneSimulator = Debug|iPhoneSimulator
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|ARM = Release|ARM
+		Release|iPhone = Release|iPhone
+		Release|iPhoneSimulator = Release|iPhoneSimulator
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Ad-Hoc|ARM.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Ad-Hoc|x64.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Ad-Hoc|x86.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.AppStore|Any CPU.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.AppStore|ARM.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.AppStore|ARM.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.AppStore|x64.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.AppStore|x64.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.AppStore|x86.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Debug|ARM.Build.0 = Debug|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Debug|x64.Build.0 = Debug|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Debug|x86.Build.0 = Debug|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Release|Any CPU.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Release|ARM.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Release|ARM.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Release|iPhone.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Release|x64.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Release|x64.Build.0 = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Release|x86.ActiveCfg = Release|Any CPU
+		{08CF175B-0057-47AF-8C8D-406010A53895}.Release|x86.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Ad-Hoc|ARM.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Ad-Hoc|x64.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Ad-Hoc|x86.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.AppStore|Any CPU.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.AppStore|ARM.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.AppStore|ARM.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.AppStore|x64.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.AppStore|x64.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.AppStore|x86.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Debug|ARM.Build.0 = Debug|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Debug|x64.Build.0 = Debug|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Debug|x86.Build.0 = Debug|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Release|Any CPU.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Release|ARM.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Release|ARM.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Release|iPhone.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Release|x64.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Release|x64.Build.0 = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Release|x86.ActiveCfg = Release|Any CPU
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73}.Release|x86.Build.0 = Release|Any CPU
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Ad-Hoc|Any CPU.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Ad-Hoc|Any CPU.Build.0 = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Ad-Hoc|ARM.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Ad-Hoc|ARM.Build.0 = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Ad-Hoc|iPhone.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Ad-Hoc|iPhone.Build.0 = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Ad-Hoc|x64.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Ad-Hoc|x64.Build.0 = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Ad-Hoc|x86.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Ad-Hoc|x86.Build.0 = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.AppStore|Any CPU.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.AppStore|Any CPU.Build.0 = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.AppStore|ARM.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.AppStore|ARM.Build.0 = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.AppStore|iPhone.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.AppStore|iPhone.Build.0 = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.AppStore|iPhoneSimulator.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.AppStore|iPhoneSimulator.Build.0 = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.AppStore|x64.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.AppStore|x64.Build.0 = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.AppStore|x86.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.AppStore|x86.Build.0 = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Debug|ARM.ActiveCfg = Debug|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Debug|iPhone.ActiveCfg = Debug|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Debug|iPhoneSimulator.ActiveCfg = Debug|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Debug|x64.ActiveCfg = Debug|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Debug|x86.ActiveCfg = Debug|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Debug|x86.Build.0 = Debug|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Release|Any CPU.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Release|ARM.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Release|iPhone.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Release|iPhoneSimulator.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Release|x64.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Release|x86.ActiveCfg = Release|x86
+		{360266C3-DF94-4A96-A1C9-915D97D6549F}.Release|x86.Build.0 = Release|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|Any CPU.ActiveCfg = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|Any CPU.Build.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|Any CPU.Deploy.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|ARM.ActiveCfg = Release|ARM
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|ARM.Build.0 = Release|ARM
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|ARM.Deploy.0 = Release|ARM
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|iPhone.ActiveCfg = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|iPhone.Build.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|iPhone.Deploy.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|x64.ActiveCfg = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|x64.Build.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|x64.Deploy.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|x86.ActiveCfg = Release|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|x86.Build.0 = Release|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Ad-Hoc|x86.Deploy.0 = Release|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|Any CPU.ActiveCfg = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|Any CPU.Build.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|Any CPU.Deploy.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|ARM.ActiveCfg = Release|ARM
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|ARM.Build.0 = Release|ARM
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|ARM.Deploy.0 = Release|ARM
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|iPhone.ActiveCfg = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|iPhone.Build.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|iPhone.Deploy.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|iPhoneSimulator.ActiveCfg = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|iPhoneSimulator.Build.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|iPhoneSimulator.Deploy.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|x64.ActiveCfg = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|x64.Build.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|x64.Deploy.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|x86.ActiveCfg = Release|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|x86.Build.0 = Release|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.AppStore|x86.Deploy.0 = Release|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Debug|ARM.ActiveCfg = Debug|ARM
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Debug|ARM.Build.0 = Debug|ARM
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Debug|ARM.Deploy.0 = Debug|ARM
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Debug|iPhone.ActiveCfg = Debug|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Debug|iPhoneSimulator.ActiveCfg = Debug|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Debug|x64.ActiveCfg = Debug|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Debug|x64.Build.0 = Debug|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Debug|x64.Deploy.0 = Debug|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Debug|x86.ActiveCfg = Debug|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Debug|x86.Build.0 = Debug|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Debug|x86.Deploy.0 = Debug|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Release|Any CPU.ActiveCfg = Release|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Release|ARM.ActiveCfg = Release|ARM
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Release|ARM.Build.0 = Release|ARM
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Release|ARM.Deploy.0 = Release|ARM
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Release|iPhone.ActiveCfg = Release|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Release|iPhoneSimulator.ActiveCfg = Release|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Release|x64.ActiveCfg = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Release|x64.Build.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Release|x64.Deploy.0 = Release|x64
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Release|x86.ActiveCfg = Release|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Release|x86.Build.0 = Release|x86
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB}.Release|x86.Deploy.0 = Release|x86
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|ARM.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|ARM.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|iPhone.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|x64.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|x64.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|x86.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Ad-Hoc|x86.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|Any CPU.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|Any CPU.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|ARM.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|ARM.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|ARM.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|iPhone.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|iPhoneSimulator.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|x64.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|x64.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|x64.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|x86.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.AppStore|x86.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|ARM.Build.0 = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|ARM.Deploy.0 = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|iPhone.Deploy.0 = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|x64.Build.0 = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|x64.Deploy.0 = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|x86.Build.0 = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Debug|x86.Deploy.0 = Debug|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|Any CPU.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|Any CPU.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|ARM.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|ARM.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|ARM.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|iPhone.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|iPhone.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|x64.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|x64.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|x64.Deploy.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|x86.ActiveCfg = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|x86.Build.0 = Release|Any CPU
+		{39138599-48BD-4DCF-83AF-78DBB4C23277}.Release|x86.Deploy.0 = Release|Any CPU
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Ad-Hoc|ARM.ActiveCfg = Ad-Hoc|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Ad-Hoc|x64.ActiveCfg = Ad-Hoc|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Ad-Hoc|x86.ActiveCfg = Ad-Hoc|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.AppStore|ARM.ActiveCfg = AppStore|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.AppStore|iPhone.Build.0 = AppStore|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.AppStore|x64.ActiveCfg = AppStore|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.AppStore|x86.ActiveCfg = AppStore|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Debug|Any CPU.ActiveCfg = Debug|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Debug|ARM.ActiveCfg = Debug|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Debug|iPhone.ActiveCfg = Debug|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Debug|iPhone.Build.0 = Debug|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Debug|x64.ActiveCfg = Debug|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Debug|x86.ActiveCfg = Debug|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Release|Any CPU.ActiveCfg = Release|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Release|ARM.ActiveCfg = Release|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Release|iPhone.ActiveCfg = Release|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Release|iPhone.Build.0 = Release|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Release|x64.ActiveCfg = Release|iPhone
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}.Release|x86.ActiveCfg = Release|iPhone
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{055FEDD0-AB52-45CE-A74D-48C009E4DB73} = {B7157C98-57CE-457E-A45C-9D1D746A7B93}
+		{360266C3-DF94-4A96-A1C9-915D97D6549F} = {B7157C98-57CE-457E-A45C-9D1D746A7B93}
+		{98E44B20-48E2-4B36-9A87-D626E2C598BB} = {B7157C98-57CE-457E-A45C-9D1D746A7B93}
+		{39138599-48BD-4DCF-83AF-78DBB4C23277} = {B7157C98-57CE-457E-A45C-9D1D746A7B93}
+		{F70F5F39-72F9-45FC-97DA-FAA70C66BA65} = {B7157C98-57CE-457E-A45C-9D1D746A7B93}
+	EndGlobalSection
+EndGlobal

+ 27 - 0
Platforms/Android/Activity1.cs

@@ -0,0 +1,27 @@
+using Android.App;
+using Android.Content.PM;
+using Android.OS;
+using Android.Views;
+
+namespace GameStateManagementSample
+{
+    [Activity(Label = "GameStateManagementSample"
+        , MainLauncher = true
+        , Icon = "@drawable/icon"
+        , Theme = "@style/Theme.Splash"
+        , AlwaysRetainTaskState = true
+        , LaunchMode = Android.Content.PM.LaunchMode.SingleInstance
+        , ScreenOrientation = ScreenOrientation.FullUser
+        , ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize)]
+    public class Activity1 : Microsoft.Xna.Framework.AndroidGameActivity
+    {
+        protected override void OnCreate(Bundle bundle)
+        {
+            base.OnCreate(bundle);
+            var g = new GameStateManagementGame();
+            SetContentView((View)g.Services.GetService(typeof(View)));
+            g.Run();
+        }
+    }
+}
+

+ 19 - 0
Platforms/Android/Assets/AboutAssets.txt

@@ -0,0 +1,19 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories) and given a Build Action of "AndroidAsset".
+
+These files will be deployed with you package and will be accessible using Android's
+AssetManager, like this:
+
+public class ReadAsset : Activity
+{
+	protected override void OnCreate (Bundle bundle)
+	{
+		base.OnCreate (bundle);
+
+		InputStream input = Assets.Open ("my_asset.txt");
+	}
+}
+
+Additionally, some Android functions will automatically load asset files:
+
+Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");

+ 15 - 0
Platforms/Android/Content/Content.mgcb

@@ -0,0 +1,15 @@
+
+#----------------------------- Global Properties ----------------------------#
+
+/outputDir:bin/$(Platform)
+/intermediateDir:obj/$(Platform)
+/platform:Android
+/config:
+/profile:Reach
+/compress:False
+
+#-------------------------------- References --------------------------------#
+
+
+#---------------------------------- Content ---------------------------------#
+

+ 153 - 0
Platforms/Android/GameStateManagementSample (Android).csproj

@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{39138599-48BD-4DCF-83AF-78DBB4C23277}</ProjectGuid>
+    <ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>GameStateManagementSample</RootNamespace>
+    <AssemblyName>GameStateManagementSample</AssemblyName>
+    <FileAlignment>512</FileAlignment>
+    <AndroidApplication>true</AndroidApplication>
+    <AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <AndroidSupportedAbis>armeabi-v7a%3bx86</AndroidSupportedAbis>
+    <AndroidStoreUncompressedFileExtensions>.m4a</AndroidStoreUncompressedFileExtensions>
+    <MandroidI18n />
+    <TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
+    <MonoGamePlatform>Android</MonoGamePlatform>
+    <AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
+    <AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;ANDROID</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
+    <AndroidLinkMode>None</AndroidLinkMode>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>TRACE;ANDROID</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
+    <AndroidLinkMode>SdkOnly</AndroidLinkMode>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Mono.Android" />
+    <Reference Include="mscorlib" />
+    <Reference Include="OpenTK-1.0" />
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Xml" />
+    <Reference Include="MonoGame.Framework">
+      <HintPath>$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\Android\MonoGame.Framework.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\SampleCode\Game.cs">
+      <Link>Game.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\ScreenFactory.cs">
+      <Link>ScreenFactory.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\BackgroundScreen.cs">
+      <Link>Screens\BackgroundScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\Button.cs">
+      <Link>Screens\Button.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\GameplayScreen.cs">
+      <Link>Screens\GameplayScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\LoadingScreen.cs">
+      <Link>Screens\LoadingScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MainMenuScreen.cs">
+      <Link>Screens\MainMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MenuEntry.cs">
+      <Link>Screens\MenuEntry.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MenuScreen.cs">
+      <Link>Screens\MenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MessageBoxScreen.cs">
+      <Link>Screens\MessageBoxScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\OptionsMenuScreen.cs">
+      <Link>Screens\OptionsMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PauseMenuScreen.cs">
+      <Link>Screens\PauseMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhoneMainMenuScreen.cs">
+      <Link>Screens\PhoneMainMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhoneMenuScreen.cs">
+      <Link>Screens\PhoneMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhonePauseScreen.cs">
+      <Link>Screens\PhonePauseScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PlayerIndexEventArgs.cs">
+      <Link>Screens\PlayerIndexEventArgs.cs</Link>
+    </Compile>
+    <Compile Include="Activity1.cs" />
+    <Compile Include="Resources\Resource.Designer.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\AboutResources.txt" />
+    <None Include="Assets\AboutAssets.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <AndroidResource Include="Resources\Values\Strings.xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <AndroidResource Include="Resources\Drawable\Icon.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Resources\Layout\" />
+  </ItemGroup>
+  <ItemGroup>
+    <AndroidResource Include="Resources\Drawable\Splash.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <AndroidResource Include="Resources\Values\Styles.xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <MonoGameContentReference Include="Content\Content.mgcb" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Properties\AndroidManifest.xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\GameStateManagement\GameStateManagement.csproj">
+      <Project>{08cf175b-0057-47af-8c8d-406010a53895}</Project>
+      <Name>GameStateManagement</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
+  <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Content.Builder.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 97 - 0
Platforms/Android/GameStateManagementSample.csproj.bak

@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{39138599-48BD-4DCF-83AF-78DBB4C23277}</ProjectGuid>
+    <ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>GameStateManagementSample</RootNamespace>
+    <AssemblyName>GameStateManagementSample</AssemblyName>
+    <FileAlignment>512</FileAlignment>
+    <AndroidApplication>true</AndroidApplication>
+    <AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <AndroidSupportedAbis>armeabi-v7a%3bx86</AndroidSupportedAbis>
+    <AndroidStoreUncompressedFileExtensions>.m4a</AndroidStoreUncompressedFileExtensions>
+    <MandroidI18n />
+    <TargetFrameworkVersion>v4.4</TargetFrameworkVersion>
+    <MonoGamePlatform>Android</MonoGamePlatform>
+    <AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
+    <AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;ANDROID</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
+    <AndroidLinkMode>None</AndroidLinkMode>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>TRACE;ANDROID</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
+    <AndroidLinkMode>SdkOnly</AndroidLinkMode>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Mono.Android" />
+    <Reference Include="mscorlib" />
+    <Reference Include="OpenTK-1.0" />
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Xml" />
+    <Reference Include="MonoGame.Framework">
+      <HintPath>$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\Android\MonoGame.Framework.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Activity1.cs" />
+    <Compile Include="Game1.cs" />
+    <Compile Include="Resources\Resource.Designer.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\AboutResources.txt" />
+    <None Include="Assets\AboutAssets.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <AndroidResource Include="Resources\Values\Strings.xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <AndroidResource Include="Resources\Drawable\Icon.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Resources\Layout\" />
+  </ItemGroup>
+  <ItemGroup>
+    <AndroidResource Include="Resources\Drawable\Splash.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <AndroidResource Include="Resources\Values\Styles.xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <MonoGameContentReference Include="Content\Content.mgcb" />
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
+  <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Content.Builder.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 5 - 0
Platforms/Android/Properties/AndroidManifest.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="GameStateManagementSample.GameStateManagementSample" android:versionCode="1" android:versionName="1.0">
+	<uses-sdk />
+	<application android:label="GameStateManagementSample" android:icon="@drawable/Icon"></application>
+</manifest>

+ 41 - 0
Platforms/Android/Properties/AssemblyInfo.cs

@@ -0,0 +1,41 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Android.App;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GameStateManagementSample")]
+[assembly: AssemblyProduct("GameStateManagementSample")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("80a7ea39-1722-4208-ac75-5853e9ab532b")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+
+// Add some common permissions, these can be removed if not needed
+[assembly: UsesPermission(Android.Manifest.Permission.Internet)]
+[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]

+ 44 - 0
Platforms/Android/Resources/AboutResources.txt

@@ -0,0 +1,44 @@
+Images, layout descriptions, binary blobs and string dictionaries can be included 
+in your application as resource files.  Various Android APIs are designed to 
+operate on the resource IDs instead of dealing with images, strings or binary blobs 
+directly.
+
+For example, a sample Android app that contains a user interface layout (Main.xml),
+an internationalization string table (Strings.xml) and some icons (drawable/Icon.png) 
+would keep its resources in the "Resources" directory of the application:
+
+Resources/
+    Drawable/
+        Icon.png
+
+    Layout/
+        Main.axml
+
+    Values/
+        Strings.xml
+
+In order to get the build system to recognize Android resources, the build action should be set 
+to "AndroidResource".  The native Android APIs do not operate directly with filenames, but 
+instead operate on resource IDs.  When you compile an Android application that uses resources, 
+the build system will package the resources for distribution and generate a class called
+"Resource" that contains the tokens for each one of the resources included. For example, 
+for the above Resources layout, this is what the Resource class would expose:
+
+public class Resource {
+    public class Drawable {
+        public const int Icon = 0x123;
+    }
+
+    public class Layout {
+        public const int Main = 0x456;
+    }
+
+    public class String {
+        public const int FirstString = 0xabc;
+        public const int SecondString = 0xbcd;
+    }
+}
+
+You would then use Resource.Drawable.Icon to reference the Drawable/Icon.png file, or 
+Resource.Layout.Main to reference the Layout/Main.axml file, or Resource.String.FirstString
+to reference the first string in the dictionary file Values/Strings.xml.

BIN
Platforms/Android/Resources/Drawable/Icon.png


BIN
Platforms/Android/Resources/Drawable/Splash.png


+ 99 - 0
Platforms/Android/Resources/Resource.Designer.cs

@@ -0,0 +1,99 @@
+#pragma warning disable 1591
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+[assembly: global::Android.Runtime.ResourceDesignerAttribute("GameStateManagementSample.Resource", IsApplication=true)]
+
+namespace GameStateManagementSample
+{
+	
+	
+	[System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
+	public partial class Resource
+	{
+		
+		static Resource()
+		{
+			global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+		}
+		
+		public static void UpdateIdValues()
+		{
+		}
+		
+		public partial class Attribute
+		{
+			
+			static Attribute()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private Attribute()
+			{
+			}
+		}
+		
+		public partial class Drawable
+		{
+			
+			// aapt resource value: 0x7f020000
+			public const int Icon = 2130837504;
+			
+			// aapt resource value: 0x7f020001
+			public const int Splash = 2130837505;
+			
+			static Drawable()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private Drawable()
+			{
+			}
+		}
+		
+		public partial class String
+		{
+			
+			// aapt resource value: 0x7f030001
+			public const int ApplicationName = 2130903041;
+			
+			// aapt resource value: 0x7f030000
+			public const int Hello = 2130903040;
+			
+			static String()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private String()
+			{
+			}
+		}
+		
+		public partial class Style
+		{
+			
+			// aapt resource value: 0x7f040000
+			public const int Theme_Splash = 2130968576;
+			
+			static Style()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private Style()
+			{
+			}
+		}
+	}
+}
+#pragma warning restore 1591

+ 5 - 0
Platforms/Android/Resources/Values/Strings.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="Hello">Hello World, Click Me!</string>
+    <string name="ApplicationName">GameStateManagementSample</string>
+</resources>

+ 7 - 0
Platforms/Android/Resources/Values/Styles.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+  <style name="Theme.Splash" parent="android:Theme">
+    <item name="android:windowBackground">@drawable/splash</item>
+    <item name="android:windowNoTitle">true</item>
+  </style>
+</resources>

+ 173 - 0
Platforms/DesktopGL/GameStateManagementSample (DesktopGL).csproj

@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{055FEDD0-AB52-45CE-A74D-48C009E4DB73}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>GameStateManagementSample</RootNamespace>
+    <AssemblyName>GameStateManagementSample</AssemblyName>
+    <FileAlignment>512</FileAlignment>
+    <MonoGamePlatform>DesktopGL</MonoGamePlatform>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;LINUX</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>false</Prefer32Bit>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
+    <OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>TRACE;LINUX</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>false</Prefer32Bit>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationIcon>Icon.ico</ApplicationIcon>
+  </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationManifest>app.manifest</ApplicationManifest>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="..\..\SampleCode\Game.cs">
+      <Link>Game.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\ScreenFactory.cs">
+      <Link>ScreenFactory.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\BackgroundScreen.cs">
+      <Link>Screens\BackgroundScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\Button.cs">
+      <Link>Screens\Button.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\GameplayScreen.cs">
+      <Link>Screens\GameplayScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\LoadingScreen.cs">
+      <Link>Screens\LoadingScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MainMenuScreen.cs">
+      <Link>Screens\MainMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MenuEntry.cs">
+      <Link>Screens\MenuEntry.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MenuScreen.cs">
+      <Link>Screens\MenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MessageBoxScreen.cs">
+      <Link>Screens\MessageBoxScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\OptionsMenuScreen.cs">
+      <Link>Screens\OptionsMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PauseMenuScreen.cs">
+      <Link>Screens\PauseMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhoneMainMenuScreen.cs">
+      <Link>Screens\PhoneMainMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhoneMenuScreen.cs">
+      <Link>Screens\PhoneMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhonePauseScreen.cs">
+      <Link>Screens\PhonePauseScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PlayerIndexEventArgs.cs">
+      <Link>Screens\PlayerIndexEventArgs.cs</Link>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="MonoGame.Framework">
+      <HintPath>$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\MonoGame.Framework.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Icon.ico" />
+    <EmbeddedResource Include="Icon.bmp" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x86\SDL2.dll">
+      <Link>x86\SDL2.dll</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x64\SDL2.dll">
+      <Link>x64\SDL2.dll</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x86\soft_oal.dll">
+      <Link>x86\soft_oal.dll</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x64\soft_oal.dll">
+      <Link>x64\soft_oal.dll</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x86\libSDL2-2.0.so.0">
+      <Link>x86\libSDL2-2.0.so.0</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x64\libSDL2-2.0.so.0">
+      <Link>x64\libSDL2-2.0.so.0</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x86\libopenal.so.1">
+      <Link>x86\libopenal.so.1</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x64\libopenal.so.1">
+      <Link>x64\libopenal.so.1</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\libSDL2-2.0.0.dylib">
+      <Link>libSDL2-2.0.0.dylib</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\libopenal.1.dylib">
+      <Link>libopenal.1.dylib</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\MonoGame.Framework.dll.config">
+      <Link>MonoGame.Framework.dll.config</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <MonoGameContentReference Include="..\..\Content\Content.mgcb">
+      <Link>Content\Content.mgcb</Link>
+    </MonoGameContentReference>
+    <None Include="app.manifest" />
+  </ItemGroup>
+  <ItemGroup />
+  <ItemGroup>
+    <ProjectReference Include="..\..\GameStateManagement\GameStateManagement.csproj">
+      <Project>{08cf175b-0057-47af-8c8d-406010a53895}</Project>
+      <Name>GameStateManagement</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Content.Builder.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

BIN
Platforms/DesktopGL/Icon.bmp


BIN
Platforms/DesktopGL/Icon.ico


+ 20 - 0
Platforms/DesktopGL/Program.cs

@@ -0,0 +1,20 @@
+using System;
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// The main class.
+    /// </summary>
+    public static class Program
+    {
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            using (var game = new GameStateManagementGame())
+                game.Run();
+        }
+    }
+}

+ 36 - 0
Platforms/DesktopGL/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GameStateManagementSample")]
+[assembly: AssemblyProduct("GameStateManagementSample")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("77781c24-ef08-44e4-bc17-9cb67b16ea10")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 42 - 0
Platforms/DesktopGL/app.manifest

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+  <assemblyIdentity version="1.0.0.0" name="GameStateManagementSample"/>
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+    <security>
+      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!-- A list of the Windows versions that this application has been tested on and is
+           is designed to work with. Uncomment the appropriate elements and Windows will 
+           automatically selected the most compatible environment. -->
+
+      <!-- Windows Vista -->
+      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
+
+      <!-- Windows 7 -->
+      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
+
+      <!-- Windows 8 -->
+      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
+
+      <!-- Windows 8.1 -->
+      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
+
+      <!-- Windows 10 -->
+      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
+
+    </application>
+  </compatibility>
+
+  <application xmlns="urn:schemas-microsoft-com:asm.v3">
+    <windowsSettings>
+      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
+    </windowsSettings>
+  </application>
+
+</assembly>

+ 127 - 0
Platforms/WindowsDX/GameStateManagementSample (WindowsDX).csproj

@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{360266C3-DF94-4A96-A1C9-915D97D6549F}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>GameStateManagementSample</RootNamespace>
+    <AssemblyName>GameStateManagementSample</AssemblyName>
+    <FileAlignment>512</FileAlignment>
+    <MonoGamePlatform>Windows</MonoGamePlatform>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;WINDOWS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>TRACE;WINDOWS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationIcon>Icon.ico</ApplicationIcon>
+  </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationManifest>app.manifest</ApplicationManifest>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="..\..\SampleCode\Game.cs">
+      <Link>Game.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\ScreenFactory.cs">
+      <Link>ScreenFactory.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\BackgroundScreen.cs">
+      <Link>Screens\BackgroundScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\Button.cs">
+      <Link>Screens\Button.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\GameplayScreen.cs">
+      <Link>Screens\GameplayScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\LoadingScreen.cs">
+      <Link>Screens\LoadingScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MainMenuScreen.cs">
+      <Link>Screens\MainMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MenuEntry.cs">
+      <Link>Screens\MenuEntry.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MenuScreen.cs">
+      <Link>Screens\MenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MessageBoxScreen.cs">
+      <Link>Screens\MessageBoxScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\OptionsMenuScreen.cs">
+      <Link>Screens\OptionsMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PauseMenuScreen.cs">
+      <Link>Screens\PauseMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhoneMainMenuScreen.cs">
+      <Link>Screens\PhoneMainMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhoneMenuScreen.cs">
+      <Link>Screens\PhoneMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhonePauseScreen.cs">
+      <Link>Screens\PhonePauseScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PlayerIndexEventArgs.cs">
+      <Link>Screens\PlayerIndexEventArgs.cs</Link>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="MonoGame.Framework">
+      <HintPath>$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\Windows\MonoGame.Framework.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Icon.ico" />
+  </ItemGroup>
+  <ItemGroup>
+    <MonoGameContentReference Include="..\..\Content\Content.mgcb">
+      <Link>Content\Content.mgcb</Link>
+    </MonoGameContentReference>
+    <None Include="app.manifest" />
+  </ItemGroup>
+  <ItemGroup />
+  <ItemGroup>
+    <ProjectReference Include="..\..\GameStateManagement\GameStateManagement.csproj">
+      <Project>{08cf175b-0057-47af-8c8d-406010a53895}</Project>
+      <Name>GameStateManagement</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Content.Builder.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

BIN
Platforms/WindowsDX/Icon.ico


+ 22 - 0
Platforms/WindowsDX/Program.cs

@@ -0,0 +1,22 @@
+using System;
+
+namespace GameStateManagementSample
+{
+#if WINDOWS || LINUX
+    /// <summary>
+    /// The main class.
+    /// </summary>
+    public static class Program
+    {
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            using (var game = new GameStateManagementGame())
+                game.Run();
+        }
+    }
+#endif
+}

+ 36 - 0
Platforms/WindowsDX/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GameStateManagementSample")]
+[assembly: AssemblyProduct("GameStateManagementSample")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("0f7b18c6-1e26-4fcd-9ff4-0d510a2f19c6")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 42 - 0
Platforms/WindowsDX/app.manifest

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+  <assemblyIdentity version="1.0.0.0" name="GameStateManagementSample"/>
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+    <security>
+      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!-- A list of the Windows versions that this application has been tested on and is
+           is designed to work with. Uncomment the appropriate elements and Windows will 
+           automatically selected the most compatible environment. -->
+
+      <!-- Windows Vista -->
+      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
+
+      <!-- Windows 7 -->
+      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
+
+      <!-- Windows 8 -->
+      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
+
+      <!-- Windows 8.1 -->
+      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
+
+      <!-- Windows 10 -->
+      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
+
+    </application>
+  </compatibility>
+
+  <application xmlns="urn:schemas-microsoft-com:asm.v3">
+    <windowsSettings>
+      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
+    </windowsSettings>
+  </application>
+
+</assembly>

+ 8 - 0
Platforms/WindowsUWP/App.xaml

@@ -0,0 +1,8 @@
+<Application
+    x:Class="GameStateManagementSample.App"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:local="using:GameStateManagementSample"
+    RequestedTheme="Light">
+
+</Application>

+ 134 - 0
Platforms/WindowsUWP/App.xaml.cs

@@ -0,0 +1,134 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+
+// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=402347&clcid=0x409
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// Provides application-specific behavior to supplement the default Application class.
+    /// </summary>
+    sealed partial class App : Application
+{
+    static string deviceFamily;
+
+    /// <summary>
+    /// Initializes the singleton application object.  This is the first line of authored code
+    /// executed, and as such is the logical equivalent of main() or WinMain().
+    /// </summary>
+    public App()
+    {
+        this.InitializeComponent();
+        this.Suspending += OnSuspending;
+
+        //API check to ensure the "RequiresPointerMode" property exists, ensuring project is running on build 14393 or later
+        if (Windows.Foundation.Metadata.ApiInformation.IsPropertyPresent("Windows.UI.Xaml.Application", "RequiresPointerMode"))
+        {
+            //If running on the Xbox, disable the default on screen pointer
+            if (IsXbox())
+            {
+                Application.Current.RequiresPointerMode = ApplicationRequiresPointerMode.WhenRequested;
+            }
+        }
+    }
+
+    /// <summary>
+    /// Detection code in Windows 10 to identify the platform it is being run on
+    /// This function returns true if the project is running on an XboxOne
+    /// </summary>
+    public static bool IsXbox()
+    {
+        if (deviceFamily == null)
+            deviceFamily = Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily;
+
+        return deviceFamily == "Windows.Xbox";
+    }
+
+    /// <summary>
+    /// Invoked when the application is launched normally by the end user.  Other entry points
+    /// will be used such as when the application is launched to open a specific file.
+    /// </summary>
+    /// <param name="e">Details about the launch request and process.</param>
+    protected override void OnLaunched(LaunchActivatedEventArgs e)
+    {
+        // By default we want to fill the entire core window.
+        ApplicationView.GetForCurrentView().SetDesiredBoundsMode(ApplicationViewBoundsMode.UseCoreWindow);
+
+#if DEBUG
+            if (System.Diagnostics.Debugger.IsAttached)
+            {
+                this.DebugSettings.EnableFrameRateCounter = true;
+            }
+#endif
+
+        Frame rootFrame = Window.Current.Content as Frame;
+
+        // Do not repeat app initialization when the Window already has content,
+        // just ensure that the window is active
+        if (rootFrame == null)
+        {
+            // Create a Frame to act as the navigation context and navigate to the first page
+            rootFrame = new Frame();
+
+            rootFrame.NavigationFailed += OnNavigationFailed;
+
+            if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
+            {
+                //TODO: Load state from previously suspended application
+            }
+
+            // Place the frame in the current Window
+            Window.Current.Content = rootFrame;
+        }
+
+        if (rootFrame.Content == null)
+        {
+            // When the navigation stack isn't restored navigate to the first page,
+            // configuring the new page by passing required information as a navigation
+            // parameter
+            rootFrame.Navigate(typeof(GamePage), e.Arguments);
+        }
+        // Ensure the current window is active
+        Window.Current.Activate();
+    }
+
+    /// <summary>
+    /// Invoked when Navigation to a certain page fails
+    /// </summary>
+    /// <param name="sender">The Frame which failed navigation</param>
+    /// <param name="e">Details about the navigation failure</param>
+    void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
+    {
+        throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
+    }
+
+    /// <summary>
+    /// Invoked when application execution is being suspended.  Application state is saved
+    /// without knowing whether the application will be terminated or resumed with the contents
+    /// of memory still intact.
+    /// </summary>
+    /// <param name="sender">The source of the suspend request.</param>
+    /// <param name="e">Details about the suspend request.</param>
+    private void OnSuspending(object sender, SuspendingEventArgs e)
+    {
+        var deferral = e.SuspendingOperation.GetDeferral();
+        //TODO: Save application state and stop any background activity
+        deferral.Complete();
+    }
+}
+}

BIN
Platforms/WindowsUWP/Assets/LockScreenLogo.scale-200.png


BIN
Platforms/WindowsUWP/Assets/SplashScreen.scale-200.png


BIN
Platforms/WindowsUWP/Assets/Square150x150Logo.scale-200.png


BIN
Platforms/WindowsUWP/Assets/Square44x44Logo.scale-200.png


BIN
Platforms/WindowsUWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png


BIN
Platforms/WindowsUWP/Assets/StoreLogo.png


BIN
Platforms/WindowsUWP/Assets/Wide310x150Logo.scale-200.png


+ 15 - 0
Platforms/WindowsUWP/Content/Content.mgcb

@@ -0,0 +1,15 @@
+
+#----------------------------- Global Properties ----------------------------#
+
+/outputDir:bin/$(Platform)
+/intermediateDir:obj/$(Platform)
+/platform:WindowsStoreApp
+/config:
+/profile:Reach
+/compress:False
+
+#-------------------------------- References --------------------------------#
+
+
+#---------------------------------- Content ---------------------------------#
+

+ 12 - 0
Platforms/WindowsUWP/GamePage.xaml

@@ -0,0 +1,12 @@
+<Page
+    x:Class="GameStateManagementSample.GamePage"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:local="using:GameStateManagementSample"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    mc:Ignorable="d">
+
+  <SwapChainPanel x:Name="swapChainPanel" />
+
+</Page>

+ 36 - 0
Platforms/WindowsUWP/GamePage.xaml.cs

@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+
+// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// An empty page that can be used on its own or navigated to within a Frame.
+    /// </summary>
+    public sealed partial class GamePage : Page
+    {
+		readonly GameStateManagementGame _game;
+
+		public GamePage()
+        {
+            this.InitializeComponent();
+
+			// Create the game.
+			var launchArguments = string.Empty;
+            _game = MonoGame.Framework.XamlGame<GameStateManagementGame>.Create(launchArguments, Window.Current.CoreWindow, swapChainPanel);
+        }
+    }
+}

+ 207 - 0
Platforms/WindowsUWP/GameStateManagementSample (UWP).csproj

@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+    <ProjectGuid>{98E44B20-48E2-4B36-9A87-D626E2C598BB}</ProjectGuid>
+    <OutputType>AppContainerExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>GameStateManagementSample</RootNamespace>
+    <AssemblyName>GameStateManagementSample</AssemblyName>
+    <DefaultLanguage>en-US</DefaultLanguage>
+    <TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
+    <TargetPlatformVersion>10.0.14393.0</TargetPlatformVersion>
+    <TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
+    <MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
+    <EnableDotNetNativeCompatibleProfile>true</EnableDotNetNativeCompatibleProfile>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <PackageCertificateKeyFile>GameStateManagementSample_TemporaryKey.pfx</PackageCertificateKeyFile>
+    <MonoGamePlatform>WindowsStoreApp</MonoGamePlatform>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\WindowsUniversal\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>full</DebugType>
+    <PlatformTarget>ARM</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+    <OutputPath>bin\WindowsUniversal\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
+    <Optimize>true</Optimize>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>ARM</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>true</Prefer32Bit>
+    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\WindowsUniversal\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\WindowsUniversal\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
+    <Optimize>true</Optimize>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>true</Prefer32Bit>
+    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\WindowsUniversal\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>bin\WindowsUniversal\$(Platform)\$(Configuration)\</OutputPath>
+    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
+    <Optimize>true</Optimize>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <Prefer32Bit>true</Prefer32Bit>
+    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
+  </PropertyGroup>
+  <ItemGroup>
+    <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
+    <Reference Include="MonoGame.Framework">
+      <HintPath>$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\WindowsUniversal\MonoGame.Framework.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\SampleCode\Game.cs">
+      <Link>Game.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\ScreenFactory.cs">
+      <Link>ScreenFactory.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\BackgroundScreen.cs">
+      <Link>Screens\BackgroundScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\Button.cs">
+      <Link>Screens\Button.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\GameplayScreen.cs">
+      <Link>Screens\GameplayScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\LoadingScreen.cs">
+      <Link>Screens\LoadingScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MainMenuScreen.cs">
+      <Link>Screens\MainMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MenuEntry.cs">
+      <Link>Screens\MenuEntry.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MenuScreen.cs">
+      <Link>Screens\MenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MessageBoxScreen.cs">
+      <Link>Screens\MessageBoxScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\OptionsMenuScreen.cs">
+      <Link>Screens\OptionsMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PauseMenuScreen.cs">
+      <Link>Screens\PauseMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhoneMainMenuScreen.cs">
+      <Link>Screens\PhoneMainMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhoneMenuScreen.cs">
+      <Link>Screens\PhoneMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhonePauseScreen.cs">
+      <Link>Screens\PhonePauseScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PlayerIndexEventArgs.cs">
+      <Link>Screens\PlayerIndexEventArgs.cs</Link>
+    </Compile>
+    <Compile Include="App.xaml.cs">
+      <DependentUpon>App.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="GamePage.xaml.cs">
+      <DependentUpon>GamePage.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <AppxManifest Include="Package.appxmanifest">
+      <SubType>Designer</SubType>
+    </AppxManifest>
+    <None Include="GameStateManagementSample_TemporaryKey.pfx" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Properties\Default.rd.xml" />
+    <Content Include="Assets\LockScreenLogo.scale-200.png" />
+    <Content Include="Assets\SplashScreen.scale-200.png" />
+    <Content Include="Assets\Square150x150Logo.scale-200.png" />
+    <Content Include="Assets\Square44x44Logo.scale-200.png" />
+    <Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
+    <Content Include="Assets\StoreLogo.png" />
+    <Content Include="Assets\Wide310x150Logo.scale-200.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <MonoGameContentReference Include="Content\Content.mgcb" />
+  </ItemGroup>
+  <ItemGroup>
+    <ApplicationDefinition Include="App.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </ApplicationDefinition>
+    <Page Include="GamePage.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
+  </ItemGroup>
+  <ItemGroup />
+  <ItemGroup>
+    <ProjectReference Include="..\..\GameStateManagement\GameStateManagement.csproj">
+      <Project>{08cf175b-0057-47af-8c8d-406010a53895}</Project>
+      <Name>GameStateManagement</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
+    <VisualStudioVersion>14.0</VisualStudioVersion>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+  <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Content.Builder.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 48 - 0
Platforms/WindowsUWP/Package.appxmanifest

@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<Package
+  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
+  xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
+  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
+  IgnorableNamespaces="uap mp">
+
+  <Identity
+    Name="1a46167e-8432-4949-941d-2c874526be92"
+    Publisher="CN=gamed"
+    Version="1.0.0.0" />
+
+  <mp:PhoneIdentity PhoneProductId="1a46167e-8432-4949-941d-2c874526be92" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
+
+  <Properties>
+    <DisplayName>GameStateManagementSample</DisplayName>
+    <PublisherDisplayName>gamed</PublisherDisplayName>
+    <Logo>Assets\StoreLogo.png</Logo>
+  </Properties>
+
+  <Dependencies>
+    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
+  </Dependencies>
+
+  <Resources>
+    <Resource Language="x-generate"/>
+  </Resources>
+
+  <Applications>
+    <Application Id="App"
+      Executable="$targetnametoken$.exe"
+      EntryPoint="GameStateManagementSample.App">
+      <uap:VisualElements
+        DisplayName="GameStateManagementSample"
+        Square150x150Logo="Assets\Logo.png"
+        Square44x44Logo="Assets\SmallLogo.png"
+        Description="GameStateManagementSample"
+        BackgroundColor="#464646">
+        <uap:SplashScreen Image="Assets\SplashScreen.png" />
+      </uap:VisualElements>
+    </Application>
+  </Applications>
+
+  <Capabilities>
+    <Capability Name="internetClient" />
+  </Capabilities>
+</Package>

+ 29 - 0
Platforms/WindowsUWP/Properties/AssemblyInfo.cs

@@ -0,0 +1,29 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GameStateManagementSample")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("GameStateManagementSample")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)]

+ 31 - 0
Platforms/WindowsUWP/Properties/Default.rd.xml

@@ -0,0 +1,31 @@
+<!--
+    This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
+    developers. However, you can modify these parameters to modify the behavior of the .NET Native
+    optimizer.
+
+    Runtime Directives are documented at http://go.microsoft.com/fwlink/?LinkID=391919
+
+    To fully enable reflection for App1.MyClass and all of its public/private members
+    <Type Name="App1.MyClass" Dynamic="Required All"/>
+
+    To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
+    <TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
+
+    Using the Namespace directive to apply reflection policy to all the types in a particular namespace
+    <Namespace Name="DataClasses.ViewModels" Seralize="All" />
+-->
+
+<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
+  <Application>
+    <!--
+      An Assembly element with Name="*Application*" applies to all assemblies in
+      the application package. The asterisks are not wildcards.
+    -->
+    <Assembly Name="*Application*" Dynamic="Required All" />
+    
+    
+    <!-- Add your application specific runtime directives here. -->
+
+
+  </Application>
+</Directives>

+ 16 - 0
Platforms/WindowsUWP/project.json

@@ -0,0 +1,16 @@
+{
+  "dependencies": {
+    "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2"
+  },
+  "frameworks": {
+    "uap10.0": {}
+  },
+  "runtimes": {
+    "win10-arm": {},
+    "win10-arm-aot": {},
+    "win10-x86": {},
+    "win10-x86-aot": {},
+    "win10-x64": {},
+    "win10-x64-aot": {}
+  }
+}

+ 13 - 0
Platforms/iOS/Content/Content.mgcb

@@ -0,0 +1,13 @@
+#----------------------------- Global Properties ----------------------------#
+
+/outputDir:bin/$(Platform)
+/intermediateDir:obj/$(Platform)
+/platform:iOS
+/config:
+/profile:Reach
+/compress:False
+
+#-------------------------------- References --------------------------------#
+
+
+#---------------------------------- Content ---------------------------------#

BIN
Platforms/iOS/Default.png


+ 6 - 0
Platforms/iOS/Entitlements.plist

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+</dict>
+</plist>

+ 184 - 0
Platforms/iOS/GameStateManagementSample (iOS).csproj

@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
+    <ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ProjectGuid>{F70F5F39-72F9-45FC-97DA-FAA70C66BA65}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>GameStateManagementSample</RootNamespace>
+    <IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
+    <AssemblyName>GameStateManagementSample</AssemblyName>
+    <MonoGamePlatform>iOS</MonoGamePlatform>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\$(Platform)\$(Configuration)</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <MtouchArch>i386, x86_64</MtouchArch>
+    <MtouchLink>None</MtouchLink>
+    <MtouchUseRefCounting>true</MtouchUseRefCounting>
+    <MtouchUseSGen>true</MtouchUseSGen>
+    <MtouchFastDev>true</MtouchFastDev>
+    <MtouchDebug>true</MtouchDebug>
+    <MtouchProfiling>true</MtouchProfiling>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
+    <DebugType>none</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\$(Platform)\$(Configuration)</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <MtouchArch>i386, x86_64</MtouchArch>
+    <MtouchLink>None</MtouchLink>
+    <MtouchUseRefCounting>true</MtouchUseRefCounting>
+    <MtouchUseSGen>true</MtouchUseSGen>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\$(Platform)\$(Configuration)</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <MtouchArch>ARMv7, ARMv7s, ARM64</MtouchArch>
+    <DeviceSpecificBuild>true</DeviceSpecificBuild>
+    <MtouchDebug>true</MtouchDebug>
+    <MtouchUseSGen>true</MtouchUseSGen>
+    <MtouchUseRefCounting>true</MtouchUseRefCounting>
+    <MtouchProfiling>true</MtouchProfiling>
+    <CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
+    <CodesignKey>iPhone Developer</CodesignKey>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\$(Platform)\$(Configuration)</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <MtouchArch>ARMv7, ARMv7s, ARM64</MtouchArch>
+    <MtouchUseSGen>true</MtouchUseSGen>
+    <MtouchUseRefCounting>true</MtouchUseRefCounting>
+    <CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
+    <CodesignKey>iPhone Developer</CodesignKey>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Ad-Hoc|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\$(Platform)\$(Configuration)</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <MtouchArch>ARMv7, ARMv7s, ARM64</MtouchArch>
+    <MtouchUseRefCounting>true</MtouchUseRefCounting>
+    <MtouchUseSGen>true</MtouchUseSGen>
+    <CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
+    <BuildIpa>True</BuildIpa>
+    <CodesignProvision>Automatic:AdHoc</CodesignProvision>
+    <CodesignKey>iPhone Distribution</CodesignKey>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AppStore|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\$(Platform)\$(Configuration)</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <MtouchArch>ARMv7, ARMv7s, ARM64</MtouchArch>
+    <MtouchUseSGen>true</MtouchUseSGen>
+    <MtouchUseRefCounting>true</MtouchUseRefCounting>
+    <CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
+    <CodesignProvision>Automatic:AppStore</CodesignProvision>
+    <CodesignKey>iPhone Distribution</CodesignKey>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="MonoGame.Framework, Version=3.6.0.1625, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\MonoGame.Framework.iOS.3.6.0.1625\lib\XamariniOS\MonoGame.Framework.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Core" />
+    <Reference Include="Xamarin.iOS" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\SampleCode\Game.cs">
+      <Link>Game.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\ScreenFactory.cs">
+      <Link>ScreenFactory.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\BackgroundScreen.cs">
+      <Link>Screens\BackgroundScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\Button.cs">
+      <Link>Screens\Button.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\GameplayScreen.cs">
+      <Link>Screens\GameplayScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\LoadingScreen.cs">
+      <Link>Screens\LoadingScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MainMenuScreen.cs">
+      <Link>Screens\MainMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MenuEntry.cs">
+      <Link>Screens\MenuEntry.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MenuScreen.cs">
+      <Link>Screens\MenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\MessageBoxScreen.cs">
+      <Link>Screens\MessageBoxScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\OptionsMenuScreen.cs">
+      <Link>Screens\OptionsMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PauseMenuScreen.cs">
+      <Link>Screens\PauseMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhoneMainMenuScreen.cs">
+      <Link>Screens\PhoneMainMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhoneMenuScreen.cs">
+      <Link>Screens\PhoneMenuScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PhonePauseScreen.cs">
+      <Link>Screens\PhonePauseScreen.cs</Link>
+    </Compile>
+    <Compile Include="..\..\SampleCode\Screens\PlayerIndexEventArgs.cs">
+      <Link>Screens\PlayerIndexEventArgs.cs</Link>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Entitlements.plist" />
+    <None Include="Info.plist" />
+    <MonoGameContentReference Include="Content\Content.mgcb" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <BundleResource Include="Default.png" />
+    <BundleResource Include="GameThumbnail.png" />
+  </ItemGroup>
+  <ItemGroup />
+  <ItemGroup>
+    <ProjectReference Include="..\..\GameStateManagement\GameStateManagement.csproj">
+      <Project>{08cf175b-0057-47af-8c8d-406010a53895}</Project>
+      <Name>GameStateManagement</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
+  <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Content.Builder.targets" />
+</Project>

BIN
Platforms/iOS/GameThumbnail.png


+ 23 - 0
Platforms/iOS/Info.plist

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDisplayName</key>
+	<string>GameStateManagementSample</string>
+	<key>CFBundleIconFiles</key>
+	<array>
+		<string>GameThumbnail.png</string>
+	</array>
+	<key>CFBundleIdentifier</key>
+	<string>project.MonoGame.GameStateManagementSample</string>
+	<key>MinimumOSVersion</key>
+	<string>7.0</string>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+</dict>
+</plist>

+ 31 - 0
Platforms/iOS/Program.cs

@@ -0,0 +1,31 @@
+using System;
+using Foundation;
+using UIKit;
+
+namespace GameStateManagementSample
+{
+    [Register("AppDelegate")]
+    class Program : UIApplicationDelegate
+    {
+        private static GameStateManagementGame game;
+
+        internal static void RunGame()
+        {
+            game = new GameStateManagementGame();
+            game.Run();
+        }
+
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        static void Main(string[] args)
+        {
+            UIApplication.Main(args, null, "AppDelegate");
+        }
+
+        public override void FinishedLaunching(UIApplication app)
+        {
+            RunGame();
+        }
+    }
+}

+ 34 - 0
Platforms/iOS/Properties/AssemblyInfo.cs

@@ -0,0 +1,34 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GameStateManagementSample")]
+[assembly: AssemblyProduct("GameStateManagementSample")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+

+ 4 - 0
Platforms/iOS/packages.config

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="MonoGame.Framework.iOS" version="3.6.0.1625" targetFramework="xamarinios10" />
+</packages>

+ 133 - 0
SampleCode/Game.cs

@@ -0,0 +1,133 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// Game.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System;
+using GameStateManagement;
+using Microsoft.Xna.Framework;
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// Sample showing how to manage different game states, with transitions
+    /// between menu screens, a loading screen, the game itself, and a pause
+    /// menu. This main game class is extremely simple: all the interesting
+    /// stuff happens in the ScreenManager component.
+    /// </summary>
+    public class GameStateManagementGame : Microsoft.Xna.Framework.Game
+    {
+        GraphicsDeviceManager graphics;
+        ScreenManager screenManager;
+        ScreenFactory screenFactory;
+
+        /// <summary>
+        /// The main game constructor.
+        /// </summary>
+        public GameStateManagementGame()
+        {
+            Content.RootDirectory = "Content";
+
+            graphics = new GraphicsDeviceManager(this);
+            TargetElapsedTime = TimeSpan.FromTicks(333333);
+
+#if WINDOWS_PHONE
+            graphics.IsFullScreen = true;
+
+            // Choose whether you want a landscape or portait game by using one of the two helper functions.
+            InitializeLandscapeGraphics();
+            // InitializePortraitGraphics();
+#endif
+
+            // Create the screen factory and add it to the Services
+            screenFactory = new ScreenFactory();
+            Services.AddService(typeof(IScreenFactory), screenFactory);
+
+            // Create the screen manager component.
+            screenManager = new ScreenManager(this);
+            Components.Add(screenManager);
+
+#if WINDOWS_PHONE
+            // Hook events on the PhoneApplicationService so we're notified of the application's life cycle
+            Microsoft.Phone.Shell.PhoneApplicationService.Current.Launching += 
+                new EventHandler<Microsoft.Phone.Shell.LaunchingEventArgs>(GameLaunching);
+            Microsoft.Phone.Shell.PhoneApplicationService.Current.Activated += 
+                new EventHandler<Microsoft.Phone.Shell.ActivatedEventArgs>(GameActivated);
+            Microsoft.Phone.Shell.PhoneApplicationService.Current.Deactivated += 
+                new EventHandler<Microsoft.Phone.Shell.DeactivatedEventArgs>(GameDeactivated);
+#else
+            // On Windows and Xbox we just add the initial screens
+            AddInitialScreens();
+#endif
+        }
+
+        private void AddInitialScreens()
+        {
+            // Activate the first screens.
+            screenManager.AddScreen(new BackgroundScreen(), null);
+
+            // We have different menus for Windows Phone to take advantage of the touch interface
+#if WINDOWS_PHONE
+            screenManager.AddScreen(new PhoneMainMenuScreen(), null);
+#else
+            screenManager.AddScreen(new MainMenuScreen(), null);
+#endif
+        }
+
+        /// <summary>
+        /// This is called when the game should draw itself.
+        /// </summary>
+        protected override void Draw(GameTime gameTime)
+        {
+            graphics.GraphicsDevice.Clear(Color.Black);
+
+            // The real drawing happens inside the screen manager component.
+            base.Draw(gameTime);
+        }
+
+#if WINDOWS_PHONE
+        /// <summary>
+        /// Helper method to the initialize the game to be a portrait game.
+        /// </summary>
+        private void InitializePortraitGraphics()
+        {
+            graphics.PreferredBackBufferWidth = 480;
+            graphics.PreferredBackBufferHeight = 800;
+        }
+
+        /// <summary>
+        /// Helper method to initialize the game to be a landscape game.
+        /// </summary>
+        private void InitializeLandscapeGraphics()
+        {
+            graphics.PreferredBackBufferWidth = 800;
+            graphics.PreferredBackBufferHeight = 480;
+        }
+
+        void GameLaunching(object sender, Microsoft.Phone.Shell.LaunchingEventArgs e)
+        {
+            AddInitialScreens();
+        }
+
+        void GameActivated(object sender, Microsoft.Phone.Shell.ActivatedEventArgs e)
+        {
+            // Try to deserialize the screen manager
+            if (!screenManager.Activate(e.IsApplicationInstancePreserved))
+            {
+                // If the screen manager fails to deserialize, add the initial screens
+                AddInitialScreens();
+            }
+        }
+
+        void GameDeactivated(object sender, Microsoft.Phone.Shell.DeactivatedEventArgs e)
+        {
+            // Serialize the screen manager when the game deactivated
+            screenManager.Deactivate();
+        }
+#endif
+    }
+}

+ 44 - 0
SampleCode/ScreenFactory.cs

@@ -0,0 +1,44 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// ScreenFactory.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System;
+using GameStateManagement;
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// Our game's implementation of IScreenFactory which can handle creating the screens
+    /// when resuming from being tombstoned.
+    /// </summary>
+    public class ScreenFactory : IScreenFactory
+    {
+        public GameScreen CreateScreen(Type screenType)
+        {
+            // All of our screens have empty constructors so we can just use Activator
+            return Activator.CreateInstance(screenType) as GameScreen;
+
+            // If we had more complex screens that had constructors or needed properties set,
+            // we could do that before handing the screen back to the ScreenManager. For example
+            // you might have something like this:
+            //
+            // if (screenType == typeof(MySuperGameScreen))
+            // {
+            //     bool value = GetFirstParameter();
+            //     float value2 = GetSecondParameter();
+            //     MySuperGameScreen screen = new MySuperGameScreen(value, value2);
+            //     return screen;
+            // }
+            //
+            // This lets you still take advantage of constructor arguments yet participate in the
+            // serialization process of the screen manager. Of course you need to save out those
+            // values when deactivating and read them back, but that means either IsolatedStorage or
+            // using the PhoneApplicationService.Current.State dictionary.
+        }
+    }
+}

+ 114 - 0
SampleCode/Screens/BackgroundScreen.cs

@@ -0,0 +1,114 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// BackgroundScreen.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;
+using GameStateManagement;
+#endregion
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// The background screen sits behind all the other menu screens.
+    /// It draws a background image that remains fixed in place regardless
+    /// of whatever transitions the screens on top of it may be doing.
+    /// </summary>
+    class BackgroundScreen : GameScreen
+    {
+        #region Fields
+
+        ContentManager content;
+        Texture2D backgroundTexture;
+
+        #endregion
+
+        #region Initialization
+
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        public BackgroundScreen()
+        {
+            TransitionOnTime = TimeSpan.FromSeconds(0.5);
+            TransitionOffTime = TimeSpan.FromSeconds(0.5);
+        }
+
+
+        /// <summary>
+        /// Loads graphics content for this screen. The background texture is quite
+        /// big, so we use our own local ContentManager to load it. This allows us
+        /// to unload before going from the menus into the game itself, wheras if we
+        /// used the shared ContentManager provided by the Game class, the content
+        /// would remain loaded forever.
+        /// </summary>
+        public override void Activate(bool instancePreserved)
+        {
+            if (!instancePreserved)
+            {
+                if (content == null)
+                    content = new ContentManager(ScreenManager.Game.Services, "Content");
+
+                backgroundTexture = content.Load<Texture2D>("background");
+            }
+        }
+
+
+        /// <summary>
+        /// Unloads graphics content for this screen.
+        /// </summary>
+        public override void Unload()
+        {
+            content.Unload();
+        }
+
+
+        #endregion
+
+        #region Update and Draw
+
+
+        /// <summary>
+        /// Updates the background screen. Unlike most screens, this should not
+        /// transition off even if it has been covered by another screen: it is
+        /// supposed to be covered, after all! This overload forces the
+        /// coveredByOtherScreen parameter to false in order to stop the base
+        /// Update method wanting to transition off.
+        /// </summary>
+        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
+                                                       bool coveredByOtherScreen)
+        {
+            base.Update(gameTime, otherScreenHasFocus, false);
+        }
+
+
+        /// <summary>
+        /// Draws the background screen.
+        /// </summary>
+        public override void Draw(GameTime gameTime)
+        {
+            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
+            Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
+            Rectangle fullscreen = new Rectangle(0, 0, viewport.Width, viewport.Height);
+
+            spriteBatch.Begin();
+
+            spriteBatch.Draw(backgroundTexture, fullscreen,
+                             new Color(TransitionAlpha, TransitionAlpha, TransitionAlpha));
+
+            spriteBatch.End();
+        }
+
+
+        #endregion
+    }
+}

+ 191 - 0
SampleCode/Screens/Button.cs

@@ -0,0 +1,191 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// Button.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System;
+using GameStateManagement;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// A special button that handles toggling between "On" and "Off"
+    /// </summary>
+    class BooleanButton : Button
+    {
+        private string option;
+        private bool value;
+
+        /// <summary>
+        /// Creates a new BooleanButton.
+        /// </summary>
+        /// <param name="option">The string text to display for the option.</param>
+        /// <param name="value">The initial value of the button.</param>
+        public BooleanButton(string option, bool value)
+            : base(option)
+        {
+            this.option = option;
+            this.value = value;
+
+            GenerateText();
+        }
+
+        protected override void OnTapped()
+        {
+            // When tapped we need to toggle the value and regenerate the text
+            value = !value;
+            GenerateText();
+
+            base.OnTapped();
+        }
+
+        /// <summary>
+        /// Helper that generates the actual Text value the base class uses for drawing.
+        /// </summary>
+        private void GenerateText()
+        {
+            Text = string.Format("{0}: {1}", option, value ? "On" : "Off");
+        }
+    }
+
+    /// <summary>
+    /// Represents a touchable button.
+    /// </summary>
+    class Button
+    {
+        /// <summary>
+        /// The text displayed in the button.
+        /// </summary>
+        public string Text = "Button";
+
+        /// <summary>
+        /// The position of the top-left corner of the button.
+        /// </summary>
+        public Vector2 Position = Vector2.Zero;
+
+        /// <summary>
+        /// The size of the button.
+        /// </summary>
+        public Vector2 Size = new Vector2(250, 75);
+
+        /// <summary>
+        /// The thickness of the border drawn for the button.
+        /// </summary>
+        public int BorderThickness = 4;
+
+        /// <summary>
+        /// The color of the button border.
+        /// </summary>
+        public Color BorderColor = new Color(200, 200, 200);
+
+        /// <summary>
+        /// The color of the button background.
+        /// </summary>
+        public Color FillColor = new Color(100, 100, 100) * .75f;
+
+        /// <summary>
+        /// The color of the text.
+        /// </summary>
+        public Color TextColor = Color.White;
+
+        /// <summary>
+        /// The opacity of the button.
+        /// </summary>
+        public float Alpha = 0f;
+
+        /// <summary>
+        /// Invoked when the button is tapped.
+        /// </summary>
+        public event EventHandler<EventArgs> Tapped;
+        
+        /// <summary>
+        /// Creates a new Button.
+        /// </summary>
+        /// <param name="text">The text to display in the button.</param>
+        public Button(string text)
+        {
+            Text = text;
+        }
+
+        /// <summary>
+        /// Invokes the Tapped event and allows subclasses to perform actions when tapped.
+        /// </summary>
+        protected virtual void OnTapped()
+        {
+            if (Tapped != null)
+                Tapped(this, EventArgs.Empty);
+        }
+
+        /// <summary>
+        /// Passes a tap location to the button for handling.
+        /// </summary>
+        /// <param name="tap">The location of the tap.</param>
+        /// <returns>True if the button was tapped, false otherwise.</returns>
+        public bool HandleTap(Vector2 tap)
+        {
+            if (tap.X >= Position.X &&
+                tap.Y >= Position.Y &&
+                tap.X <= Position.X + Size.X &&
+                tap.Y <= Position.Y + Size.Y)
+            {
+                OnTapped();
+                return true;
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        /// Draws the button
+        /// </summary>
+        /// <param name="screen">The screen drawing the button</param>
+        public void Draw(GameScreen screen)
+        {
+            // Grab some common items from the ScreenManager
+            SpriteBatch spriteBatch = screen.ScreenManager.SpriteBatch;
+            SpriteFont font = screen.ScreenManager.Font;
+            Texture2D blank = screen.ScreenManager.BlankTexture;
+
+            // Compute the button's rectangle
+            Rectangle r = new Rectangle(
+                (int)Position.X,
+                (int)Position.Y,
+                (int)Size.X,
+                (int)Size.Y);
+
+            // Fill the button
+            spriteBatch.Draw(blank, r, FillColor * Alpha);
+
+            // Draw the border
+            spriteBatch.Draw(
+                blank, 
+                new Rectangle(r.Left, r.Top, r.Width, BorderThickness),
+                BorderColor * Alpha);
+            spriteBatch.Draw(
+                blank, 
+                new Rectangle(r.Left, r.Top, BorderThickness, r.Height),
+                BorderColor * Alpha);
+            spriteBatch.Draw(
+                blank, 
+                new Rectangle(r.Right - BorderThickness, r.Top, BorderThickness, r.Height),
+                BorderColor * Alpha);
+            spriteBatch.Draw(
+                blank, 
+                new Rectangle(r.Left, r.Bottom - BorderThickness, r.Width, BorderThickness),
+                BorderColor * Alpha);
+
+            // Draw the text centered in the button
+            Vector2 textSize = font.MeasureString(Text);
+            Vector2 textPosition = new Vector2(r.Center.X, r.Center.Y) - textSize / 2f;
+            textPosition.X = (int)textPosition.X;
+            textPosition.Y = (int)textPosition.Y;
+            spriteBatch.DrawString(font, Text, textPosition, TextColor * Alpha);
+        }
+    }
+}

+ 266 - 0
SampleCode/Screens/GameplayScreen.cs

@@ -0,0 +1,266 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// GameplayScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using System.Threading;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using GameStateManagement;
+#endregion
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// This screen implements the actual game logic. It is just a
+    /// placeholder to get the idea across: you'll probably want to
+    /// put some more interesting gameplay in here!
+    /// </summary>
+    class GameplayScreen : GameScreen
+    {
+        #region Fields
+
+        ContentManager content;
+        SpriteFont gameFont;
+
+        Vector2 playerPosition = new Vector2(100, 100);
+        Vector2 enemyPosition = new Vector2(100, 100);
+
+        Random random = new Random();
+
+        float pauseAlpha;
+
+        InputAction pauseAction;
+
+        #endregion
+
+        #region Initialization
+
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        public GameplayScreen()
+        {
+            TransitionOnTime = TimeSpan.FromSeconds(1.5);
+            TransitionOffTime = TimeSpan.FromSeconds(0.5);
+
+            pauseAction = new InputAction(
+                new Buttons[] { Buttons.Start, Buttons.Back },
+                new Keys[] { Keys.Escape },
+                true);
+        }
+
+
+        /// <summary>
+        /// Load graphics content for the game.
+        /// </summary>
+        public override void Activate(bool instancePreserved)
+        {
+            if (!instancePreserved)
+            {
+                if (content == null)
+                    content = new ContentManager(ScreenManager.Game.Services, "Content");
+
+                gameFont = content.Load<SpriteFont>("gamefont");
+
+                // A real game would probably have more content than this sample, so
+                // it would take longer to load. We simulate that by delaying for a
+                // while, giving you a chance to admire the beautiful loading screen.
+#if !WINDOWS_UAP
+                Thread.Sleep(1000);
+#endif
+                // once the load has finished, we use ResetElapsedTime to tell the game's
+                // timing mechanism that we have just finished a very long frame, and that
+                // it should not try to catch up.
+                ScreenManager.Game.ResetElapsedTime();
+            }
+
+#if WINDOWS_PHONE
+            if (Microsoft.Phone.Shell.PhoneApplicationService.Current.State.ContainsKey("PlayerPosition"))
+            {
+                playerPosition = (Vector2)Microsoft.Phone.Shell.PhoneApplicationService.Current.State["PlayerPosition"];
+                enemyPosition = (Vector2)Microsoft.Phone.Shell.PhoneApplicationService.Current.State["EnemyPosition"];
+            }
+#endif
+        }
+
+
+        public override void Deactivate()
+        {
+#if WINDOWS_PHONE
+            Microsoft.Phone.Shell.PhoneApplicationService.Current.State["PlayerPosition"] = playerPosition;
+            Microsoft.Phone.Shell.PhoneApplicationService.Current.State["EnemyPosition"] = enemyPosition;
+#endif
+
+            base.Deactivate();
+        }
+
+
+        /// <summary>
+        /// Unload graphics content used by the game.
+        /// </summary>
+        public override void Unload()
+        {
+            content.Unload();
+
+#if WINDOWS_PHONE
+            Microsoft.Phone.Shell.PhoneApplicationService.Current.State.Remove("PlayerPosition");
+            Microsoft.Phone.Shell.PhoneApplicationService.Current.State.Remove("EnemyPosition");
+#endif
+        }
+
+
+        #endregion
+
+        #region Update and Draw
+
+
+        /// <summary>
+        /// Updates the state of the game. This method checks the GameScreen.IsActive
+        /// property, so the game will stop updating when the pause menu is active,
+        /// or if you tab away to a different application.
+        /// </summary>
+        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
+                                                       bool coveredByOtherScreen)
+        {
+            base.Update(gameTime, otherScreenHasFocus, false);
+
+            // Gradually fade in or out depending on whether we are covered by the pause screen.
+            if (coveredByOtherScreen)
+                pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);
+            else
+                pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);
+
+            if (IsActive)
+            {
+                // Apply some random jitter to make the enemy move around.
+                const float randomization = 10;
+
+                enemyPosition.X += (float)(random.NextDouble() - 0.5) * randomization;
+                enemyPosition.Y += (float)(random.NextDouble() - 0.5) * randomization;
+
+                // Apply a stabilizing force to stop the enemy moving off the screen.
+                Vector2 targetPosition = new Vector2(
+                    ScreenManager.GraphicsDevice.Viewport.Width / 2 - gameFont.MeasureString("Insert Gameplay Here").X / 2, 
+                    200);
+
+                enemyPosition = Vector2.Lerp(enemyPosition, targetPosition, 0.05f);
+
+                // TODO: this game isn't very fun! You could probably improve
+                // it by inserting something more interesting in this space :-)
+            }
+        }
+
+
+        /// <summary>
+        /// Lets the game respond to player input. Unlike the Update method,
+        /// this will only be called when the gameplay screen is active.
+        /// </summary>
+        public override void HandleInput(GameTime gameTime, InputState input)
+        {
+            if (input == null)
+                throw new ArgumentNullException("input");
+
+            // Look up inputs for the active player profile.
+            int playerIndex = (int)ControllingPlayer.Value;
+
+            KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];
+            GamePadState gamePadState = input.CurrentGamePadStates[playerIndex];
+
+            // The game pauses either if the user presses the pause button, or if
+            // they unplug the active gamepad. This requires us to keep track of
+            // whether a gamepad was ever plugged in, because we don't want to pause
+            // on PC if they are playing with a keyboard and have no gamepad at all!
+            bool gamePadDisconnected = !gamePadState.IsConnected &&
+                                       input.GamePadWasConnected[playerIndex];
+
+            PlayerIndex player;
+            if (pauseAction.Evaluate(input, ControllingPlayer, out player) || gamePadDisconnected)
+            {
+#if WINDOWS_PHONE
+                ScreenManager.AddScreen(new PhonePauseScreen(), ControllingPlayer);
+#else
+                ScreenManager.AddScreen(new PauseMenuScreen(), ControllingPlayer);
+#endif
+            }
+            else
+            {
+                // Otherwise move the player position.
+                Vector2 movement = Vector2.Zero;
+
+                if (keyboardState.IsKeyDown(Keys.Left))
+                    movement.X--;
+
+                if (keyboardState.IsKeyDown(Keys.Right))
+                    movement.X++;
+
+                if (keyboardState.IsKeyDown(Keys.Up))
+                    movement.Y--;
+
+                if (keyboardState.IsKeyDown(Keys.Down))
+                    movement.Y++;
+
+                Vector2 thumbstick = gamePadState.ThumbSticks.Left;
+
+                movement.X += thumbstick.X;
+                movement.Y -= thumbstick.Y;
+
+                if (input.TouchState.Count > 0)
+                {
+                    Vector2 touchPosition = input.TouchState[0].Position;
+                    Vector2 direction = touchPosition - playerPosition;
+                    direction.Normalize();
+                    movement += direction;
+                }
+
+                if (movement.Length() > 1)
+                    movement.Normalize();
+
+                playerPosition += movement * 8f;
+            }
+        }
+
+
+        /// <summary>
+        /// Draws the gameplay screen.
+        /// </summary>
+        public override void Draw(GameTime gameTime)
+        {
+            // This game has a blue background. Why? Because!
+            ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
+                                               Color.CornflowerBlue, 0, 0);
+
+            // Our player and enemy are both actually just text strings.
+            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
+
+            spriteBatch.Begin();
+
+            spriteBatch.DrawString(gameFont, "// TODO", playerPosition, Color.Green);
+
+            spriteBatch.DrawString(gameFont, "Insert Gameplay Here",
+                                   enemyPosition, Color.DarkRed);
+
+            spriteBatch.End();
+
+            // If the game is transitioning on or off, fade it out to black.
+            if (TransitionPosition > 0 || pauseAlpha > 0)
+            {
+                float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);
+
+                ScreenManager.FadeBackBufferToBlack(alpha);
+            }
+        }
+
+
+        #endregion
+    }
+}

+ 163 - 0
SampleCode/Screens/LoadingScreen.cs

@@ -0,0 +1,163 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// LoadingScreen.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.Graphics;
+using GameStateManagement;
+#endregion
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// The loading screen coordinates transitions between the menu system and the
+    /// game itself. Normally one screen will transition off at the same time as
+    /// the next screen is transitioning on, but for larger transitions that can
+    /// take a longer time to load their data, we want the menu system to be entirely
+    /// gone before we start loading the game. This is done as follows:
+    /// 
+    /// - Tell all the existing screens to transition off.
+    /// - Activate a loading screen, which will transition on at the same time.
+    /// - The loading screen watches the state of the previous screens.
+    /// - When it sees they have finished transitioning off, it activates the real
+    ///   next screen, which may take a long time to load its data. The loading
+    ///   screen will be the only thing displayed while this load is taking place.
+    /// </summary>
+    class LoadingScreen : GameScreen
+    {
+        #region Fields
+
+        bool loadingIsSlow;
+        bool otherScreensAreGone;
+
+        GameScreen[] screensToLoad;
+
+        #endregion
+
+        #region Initialization
+
+
+        /// <summary>
+        /// The constructor is private: loading screens should
+        /// be activated via the static Load method instead.
+        /// </summary>
+        private LoadingScreen(ScreenManager screenManager, bool loadingIsSlow,
+                              GameScreen[] screensToLoad)
+        {
+            this.loadingIsSlow = loadingIsSlow;
+            this.screensToLoad = screensToLoad;
+
+            TransitionOnTime = TimeSpan.FromSeconds(0.5);
+        }
+
+
+        /// <summary>
+        /// Activates the loading screen.
+        /// </summary>
+        public static void Load(ScreenManager screenManager, bool loadingIsSlow,
+                                PlayerIndex? controllingPlayer,
+                                params GameScreen[] screensToLoad)
+        {
+            // Tell all the current screens to transition off.
+            foreach (GameScreen screen in screenManager.GetScreens())
+                screen.ExitScreen();
+
+            // Create and activate the loading screen.
+            LoadingScreen loadingScreen = new LoadingScreen(screenManager,
+                                                            loadingIsSlow,
+                                                            screensToLoad);
+
+            screenManager.AddScreen(loadingScreen, controllingPlayer);
+        }
+
+
+        #endregion
+
+        #region Update and Draw
+
+
+        /// <summary>
+        /// Updates the loading screen.
+        /// </summary>
+        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
+                                                       bool coveredByOtherScreen)
+        {
+            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
+
+            // If all the previous screens have finished transitioning
+            // off, it is time to actually perform the load.
+            if (otherScreensAreGone)
+            {
+                ScreenManager.RemoveScreen(this);
+
+                foreach (GameScreen screen in screensToLoad)
+                {
+                    if (screen != null)
+                    {
+                        ScreenManager.AddScreen(screen, ControllingPlayer);
+                    }
+                }
+
+                // Once the load has finished, we use ResetElapsedTime to tell
+                // the  game timing mechanism that we have just finished a very
+                // long frame, and that it should not try to catch up.
+                ScreenManager.Game.ResetElapsedTime();
+            }
+        }
+
+
+        /// <summary>
+        /// Draws the loading screen.
+        /// </summary>
+        public override void Draw(GameTime gameTime)
+        {
+            // If we are the only active screen, that means all the previous screens
+            // must have finished transitioning off. We check for this in the Draw
+            // method, rather than in Update, because it isn't enough just for the
+            // screens to be gone: in order for the transition to look good we must
+            // have actually drawn a frame without them before we perform the load.
+            if ((ScreenState == ScreenState.Active) &&
+                (ScreenManager.GetScreens().Length == 1))
+            {
+                otherScreensAreGone = true;
+            }
+
+            // The gameplay screen takes a while to load, so we display a loading
+            // message while that is going on, but the menus load very quickly, and
+            // it would look silly if we flashed this up for just a fraction of a
+            // second while returning from the game to the menus. This parameter
+            // tells us how long the loading is going to take, so we know whether
+            // to bother drawing the message.
+            if (loadingIsSlow)
+            {
+                SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
+                SpriteFont font = ScreenManager.Font;
+
+                const string message = "Loading...";
+
+                // Center the text in the viewport.
+                Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
+                Vector2 viewportSize = new Vector2(viewport.Width, viewport.Height);
+                Vector2 textSize = font.MeasureString(message);
+                Vector2 textPosition = (viewportSize - textSize) / 2;
+
+                Color color = Color.White * TransitionAlpha;
+
+                // Draw the text.
+                spriteBatch.Begin();
+                spriteBatch.DrawString(font, message, textPosition, color);
+                spriteBatch.End();
+            }
+        }
+
+
+        #endregion
+    }
+}

+ 98 - 0
SampleCode/Screens/MainMenuScreen.cs

@@ -0,0 +1,98 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// MainMenuScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using Microsoft.Xna.Framework;
+#endregion
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// The main menu screen is the first thing displayed when the game starts up.
+    /// </summary>
+    class MainMenuScreen : MenuScreen
+    {
+        #region Initialization
+
+
+        /// <summary>
+        /// Constructor fills in the menu contents.
+        /// </summary>
+        public MainMenuScreen()
+            : base("Main Menu")
+        {
+            // Create our menu entries.
+            MenuEntry playGameMenuEntry = new MenuEntry("Play Game");
+            MenuEntry optionsMenuEntry = new MenuEntry("Options");
+            MenuEntry exitMenuEntry = new MenuEntry("Exit");
+
+            // Hook up menu event handlers.
+            playGameMenuEntry.Selected += PlayGameMenuEntrySelected;
+            optionsMenuEntry.Selected += OptionsMenuEntrySelected;
+            exitMenuEntry.Selected += OnCancel;
+
+            // Add entries to the menu.
+            MenuEntries.Add(playGameMenuEntry);
+            MenuEntries.Add(optionsMenuEntry);
+            MenuEntries.Add(exitMenuEntry);
+        }
+
+
+        #endregion
+
+        #region Handle Input
+
+
+        /// <summary>
+        /// Event handler for when the Play Game menu entry is selected.
+        /// </summary>
+        void PlayGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+        {
+            LoadingScreen.Load(ScreenManager, true, e.PlayerIndex,
+                               new GameplayScreen());
+        }
+
+
+        /// <summary>
+        /// Event handler for when the Options menu entry is selected.
+        /// </summary>
+        void OptionsMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+        {
+            ScreenManager.AddScreen(new OptionsMenuScreen(), e.PlayerIndex);
+        }
+
+
+#if !__IOS__
+        /// <summary>
+        /// When the user cancels the main menu, ask if they want to exit the sample.
+        /// </summary>
+        protected override void OnCancel(PlayerIndex playerIndex)
+        {
+            const string message = "Are you sure you want to exit this sample?";
+
+            MessageBoxScreen confirmExitMessageBox = new MessageBoxScreen(message);
+
+            confirmExitMessageBox.Accepted += ConfirmExitMessageBoxAccepted;
+
+            ScreenManager.AddScreen(confirmExitMessageBox, playerIndex);
+        }
+
+        /// <summary>
+        /// Event handler for when the user selects ok on the "are you sure
+        /// you want to exit" message box.
+        /// </summary>
+        void ConfirmExitMessageBoxAccepted(object sender, PlayerIndexEventArgs e)
+        {
+            ScreenManager.Game.Exit();
+        }
+#endif
+
+#endregion
+    }
+}

+ 192 - 0
SampleCode/Screens/MenuEntry.cs

@@ -0,0 +1,192 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// MenuEntry.cs
+//
+// 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.Graphics;
+using GameStateManagement;
+#endregion
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// Helper class represents a single entry in a MenuScreen. By default this
+    /// just draws the entry text string, but it can be customized to display menu
+    /// entries in different ways. This also provides an event that will be raised
+    /// when the menu entry is selected.
+    /// </summary>
+    class MenuEntry
+    {
+        #region Fields
+
+        /// <summary>
+        /// The text rendered for this entry.
+        /// </summary>
+        string text;
+
+        /// <summary>
+        /// Tracks a fading selection effect on the entry.
+        /// </summary>
+        /// <remarks>
+        /// The entries transition out of the selection effect when they are deselected.
+        /// </remarks>
+        float selectionFade;
+
+        /// <summary>
+        /// The position at which the entry is drawn. This is set by the MenuScreen
+        /// each frame in Update.
+        /// </summary>
+        Vector2 position;
+
+        #endregion
+
+        #region Properties
+
+
+        /// <summary>
+        /// Gets or sets the text of this menu entry.
+        /// </summary>
+        public string Text
+        {
+            get { return text; }
+            set { text = value; }
+        }
+
+
+        /// <summary>
+        /// Gets or sets the position at which to draw this menu entry.
+        /// </summary>
+        public Vector2 Position
+        {
+            get { return position; }
+            set { position = value; }
+        }
+
+
+        #endregion
+
+        #region Events
+
+
+        /// <summary>
+        /// Event raised when the menu entry is selected.
+        /// </summary>
+        public event EventHandler<PlayerIndexEventArgs> Selected;
+
+
+        /// <summary>
+        /// Method for raising the Selected event.
+        /// </summary>
+        protected internal virtual void OnSelectEntry(PlayerIndex playerIndex)
+        {
+            if (Selected != null)
+                Selected(this, new PlayerIndexEventArgs(playerIndex));
+        }
+
+
+        #endregion
+
+        #region Initialization
+
+
+        /// <summary>
+        /// Constructs a new menu entry with the specified text.
+        /// </summary>
+        public MenuEntry(string text)
+        {
+            this.text = text;
+        }
+
+
+        #endregion
+
+        #region Update and Draw
+
+
+        /// <summary>
+        /// Updates the menu entry.
+        /// </summary>
+        public virtual void Update(MenuScreen screen, bool isSelected, GameTime gameTime)
+        {
+            // there is no such thing as a selected item on Windows Phone, so we always
+            // force isSelected to be false
+#if WINDOWS_PHONE
+            isSelected = false;
+#endif
+
+            // When the menu selection changes, entries gradually fade between
+            // their selected and deselected appearance, rather than instantly
+            // popping to the new state.
+            float fadeSpeed = (float)gameTime.ElapsedGameTime.TotalSeconds * 4;
+
+            if (isSelected)
+                selectionFade = Math.Min(selectionFade + fadeSpeed, 1);
+            else
+                selectionFade = Math.Max(selectionFade - fadeSpeed, 0);
+        }
+
+
+        /// <summary>
+        /// Draws the menu entry. This can be overridden to customize the appearance.
+        /// </summary>
+        public virtual void Draw(MenuScreen screen, bool isSelected, GameTime gameTime)
+        {
+            // there is no such thing as a selected item on Windows Phone, so we always
+            // force isSelected to be false
+#if WINDOWS_PHONE
+            isSelected = false;
+#endif
+
+            // Draw the selected entry in yellow, otherwise white.
+            Color color = isSelected ? Color.Yellow : Color.White;
+
+            // Pulsate the size of the selected menu entry.
+            double time = gameTime.TotalGameTime.TotalSeconds;
+            
+            float pulsate = (float)Math.Sin(time * 6) + 1;
+
+            float scale = 1 + pulsate * 0.05f * selectionFade;
+
+            // Modify the alpha to fade text out during transitions.
+            color *= screen.TransitionAlpha;
+
+            // Draw text, centered on the middle of each line.
+            ScreenManager screenManager = screen.ScreenManager;
+            SpriteBatch spriteBatch = screenManager.SpriteBatch;
+            SpriteFont font = screenManager.Font;
+
+            Vector2 origin = new Vector2(0, font.LineSpacing / 2);
+
+            spriteBatch.DrawString(font, text, position, color, 0,
+                                   origin, scale, SpriteEffects.None, 0);
+        }
+
+
+        /// <summary>
+        /// Queries how much space this menu entry requires.
+        /// </summary>
+        public virtual int GetHeight(MenuScreen screen)
+        {
+            return screen.ScreenManager.Font.LineSpacing;
+        }
+
+
+        /// <summary>
+        /// Queries how wide the entry is, used for centering on the screen.
+        /// </summary>
+        public virtual int GetWidth(MenuScreen screen)
+        {
+            return (int)screen.ScreenManager.Font.MeasureString(Text).X;
+        }
+
+
+        #endregion
+    }
+}

+ 267 - 0
SampleCode/Screens/MenuScreen.cs

@@ -0,0 +1,267 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// MenuScreen.cs
+//
+// XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input.Touch;
+using Microsoft.Xna.Framework.Input;
+using GameStateManagement;
+#endregion
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// Base class for screens that contain a menu of options. The user can
+    /// move up and down to select an entry, or cancel to back out of the screen.
+    /// </summary>
+    abstract class MenuScreen : GameScreen
+    {
+        #region Fields
+
+        List<MenuEntry> menuEntries = new List<MenuEntry>();
+        int selectedEntry = 0;
+        string menuTitle;
+
+        InputAction menuUp;
+        InputAction menuDown;
+        InputAction menuSelect;
+        InputAction menuCancel;
+
+        #endregion
+
+        #region Properties
+
+
+        /// <summary>
+        /// Gets the list of menu entries, so derived classes can add
+        /// or change the menu contents.
+        /// </summary>
+        protected IList<MenuEntry> MenuEntries
+        {
+            get { return menuEntries; }
+        }
+
+
+        #endregion
+
+        #region Initialization
+
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        public MenuScreen(string menuTitle)
+        {
+            this.menuTitle = menuTitle;
+
+            TransitionOnTime = TimeSpan.FromSeconds(0.5);
+            TransitionOffTime = TimeSpan.FromSeconds(0.5);
+
+            menuUp = new InputAction(
+                new Buttons[] { Buttons.DPadUp, Buttons.LeftThumbstickUp }, 
+                new Keys[] { Keys.Up },
+                true);
+            menuDown = new InputAction(
+                new Buttons[] { Buttons.DPadDown, Buttons.LeftThumbstickDown },
+                new Keys[] { Keys.Down },
+                true);
+            menuSelect = new InputAction(
+                new Buttons[] { Buttons.A, Buttons.Start },
+                new Keys[] { Keys.Enter, Keys.Space },
+                true);
+            menuCancel = new InputAction(
+                new Buttons[] { Buttons.B, Buttons.Back },
+                new Keys[] { Keys.Escape },
+                true);
+        }
+
+
+        #endregion
+
+        #region Handle Input
+
+
+        /// <summary>
+        /// Responds to user input, changing the selected entry and accepting
+        /// or cancelling the menu.
+        /// </summary>
+        public override void HandleInput(GameTime gameTime, InputState input)
+        {
+            // For input tests we pass in our ControllingPlayer, which may
+            // either be null (to accept input from any player) or a specific index.
+            // If we pass a null controlling player, the InputState helper returns to
+            // us which player actually provided the input. We pass that through to
+            // OnSelectEntry and OnCancel, so they can tell which player triggered them.
+            PlayerIndex playerIndex;
+
+            // Move to the previous menu entry?
+            if (menuUp.Evaluate(input, ControllingPlayer, out playerIndex))
+            {
+                selectedEntry--;
+
+                if (selectedEntry < 0)
+                    selectedEntry = menuEntries.Count - 1;
+            }
+
+            // Move to the next menu entry?
+            if (menuDown.Evaluate(input, ControllingPlayer, out playerIndex))
+            {
+                selectedEntry++;
+
+                if (selectedEntry >= menuEntries.Count)
+                    selectedEntry = 0;
+            }
+
+            if (menuSelect.Evaluate(input, ControllingPlayer, out playerIndex))
+            {
+                OnSelectEntry(selectedEntry, playerIndex);
+            }
+            else if (menuCancel.Evaluate(input, ControllingPlayer, out playerIndex))
+            {
+                OnCancel(playerIndex);
+            }
+        }
+
+
+        /// <summary>
+        /// Handler for when the user has chosen a menu entry.
+        /// </summary>
+        protected virtual void OnSelectEntry(int entryIndex, PlayerIndex playerIndex)
+        {
+            menuEntries[entryIndex].OnSelectEntry(playerIndex);
+        }
+
+
+        /// <summary>
+        /// Handler for when the user has cancelled the menu.
+        /// </summary>
+        protected virtual void OnCancel(PlayerIndex playerIndex)
+        {
+            ExitScreen();
+        }
+
+
+        /// <summary>
+        /// Helper overload makes it easy to use OnCancel as a MenuEntry event handler.
+        /// </summary>
+        protected void OnCancel(object sender, PlayerIndexEventArgs e)
+        {
+            OnCancel(e.PlayerIndex);
+        }
+
+
+        #endregion
+
+        #region Update and Draw
+
+
+        /// <summary>
+        /// Allows the screen the chance to position the menu entries. By default
+        /// all menu entries are lined up in a vertical list, centered on the screen.
+        /// </summary>
+        protected virtual void UpdateMenuEntryLocations()
+        {
+            // Make the menu slide into place during transitions, using a
+            // power curve to make things look more interesting (this makes
+            // the movement slow down as it nears the end).
+            float transitionOffset = (float)Math.Pow(TransitionPosition, 2);
+
+            // start at Y = 175; each X value is generated per entry
+            Vector2 position = new Vector2(0f, 175f);
+
+            // update each menu entry's location in turn
+            for (int i = 0; i < menuEntries.Count; i++)
+            {
+                MenuEntry menuEntry = menuEntries[i];
+                
+                // each entry is to be centered horizontally
+                position.X = ScreenManager.GraphicsDevice.Viewport.Width / 2 - menuEntry.GetWidth(this) / 2;
+
+                if (ScreenState == ScreenState.TransitionOn)
+                    position.X -= transitionOffset * 256;
+                else
+                    position.X += transitionOffset * 512;
+
+                // set the entry's position
+                menuEntry.Position = position;
+
+                // move down for the next entry the size of this entry
+                position.Y += menuEntry.GetHeight(this);
+            }
+        }
+
+
+        /// <summary>
+        /// Updates the menu.
+        /// </summary>
+        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
+                                                       bool coveredByOtherScreen)
+        {
+            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
+
+            // Update each nested MenuEntry object.
+            for (int i = 0; i < menuEntries.Count; i++)
+            {
+                bool isSelected = IsActive && (i == selectedEntry);
+
+                menuEntries[i].Update(this, isSelected, gameTime);
+            }
+        }
+
+
+        /// <summary>
+        /// Draws the menu.
+        /// </summary>
+        public override void Draw(GameTime gameTime)
+        {
+            // make sure our entries are in the right place before we draw them
+            UpdateMenuEntryLocations();
+
+            GraphicsDevice graphics = ScreenManager.GraphicsDevice;
+            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
+            SpriteFont font = ScreenManager.Font;
+
+            spriteBatch.Begin();
+
+            // Draw each menu entry in turn.
+            for (int i = 0; i < menuEntries.Count; i++)
+            {
+                MenuEntry menuEntry = menuEntries[i];
+
+                bool isSelected = IsActive && (i == selectedEntry);
+
+                menuEntry.Draw(this, isSelected, gameTime);
+            }
+
+            // Make the menu slide into place during transitions, using a
+            // power curve to make things look more interesting (this makes
+            // the movement slow down as it nears the end).
+            float transitionOffset = (float)Math.Pow(TransitionPosition, 2);
+
+            // Draw the menu title centered on the screen
+            Vector2 titlePosition = new Vector2(graphics.Viewport.Width / 2, 80);
+            Vector2 titleOrigin = font.MeasureString(menuTitle) / 2;
+            Color titleColor = new Color(192, 192, 192) * TransitionAlpha;
+            float titleScale = 1.25f;
+
+            titlePosition.Y -= transitionOffset * 100;
+
+            spriteBatch.DrawString(font, menuTitle, titlePosition, titleColor, 0,
+                                   titleOrigin, titleScale, SpriteEffects.None, 0);
+
+            spriteBatch.End();
+        }
+
+
+        #endregion
+    }
+}

+ 186 - 0
SampleCode/Screens/MessageBoxScreen.cs

@@ -0,0 +1,186 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// MessageBoxScreen.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;
+using Microsoft.Xna.Framework.Input;
+using GameStateManagement;
+#endregion
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// A popup message box screen, used to display "are you sure?"
+    /// confirmation messages.
+    /// </summary>
+    class MessageBoxScreen : GameScreen
+    {
+        #region Fields
+
+        string message;
+        Texture2D gradientTexture;
+
+        InputAction menuSelect;
+        InputAction menuCancel;
+
+        #endregion
+
+        #region Events
+
+        public event EventHandler<PlayerIndexEventArgs> Accepted;
+        public event EventHandler<PlayerIndexEventArgs> Cancelled;
+
+        #endregion
+
+        #region Initialization
+
+
+        /// <summary>
+        /// Constructor automatically includes the standard "A=ok, B=cancel"
+        /// usage text prompt.
+        /// </summary>
+        public MessageBoxScreen(string message)
+            : this(message, true)
+        { }
+
+
+        /// <summary>
+        /// Constructor lets the caller specify whether to include the standard
+        /// "A=ok, B=cancel" usage text prompt.
+        /// </summary>
+        public MessageBoxScreen(string message, bool includeUsageText)
+        {
+            const string usageText = "\nA button, Space, Enter = ok" +
+                                     "\nB button, Esc = cancel"; 
+            
+            if (includeUsageText)
+                this.message = message + usageText;
+            else
+                this.message = message;
+
+            IsPopup = true;
+
+            TransitionOnTime = TimeSpan.FromSeconds(0.2);
+            TransitionOffTime = TimeSpan.FromSeconds(0.2);
+
+            menuSelect = new InputAction(
+                new Buttons[] { Buttons.A, Buttons.Start },
+                new Keys[] { Keys.Space, Keys.Enter },
+                true);
+            menuCancel = new InputAction(
+                new Buttons[] { Buttons.B, Buttons.Back },
+                new Keys[] { Keys.Escape, Keys.Back },
+                true);
+        }
+
+
+        /// <summary>
+        /// 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 MessageBoxScreen tries to load this same content,
+        /// it will just get back another reference to the already loaded data.
+        /// </summary>
+        public override void Activate(bool instancePreserved)
+        {
+            if (!instancePreserved)
+            {
+                ContentManager content = ScreenManager.Game.Content;
+                gradientTexture = content.Load<Texture2D>("gradient");
+            }
+        }
+
+
+        #endregion
+
+        #region Handle Input
+
+
+        /// <summary>
+        /// Responds to user input, accepting or cancelling the message box.
+        /// </summary>
+        public override void HandleInput(GameTime gameTime, InputState input)
+        {
+            PlayerIndex playerIndex;
+
+            // We pass in our ControllingPlayer, which may either be null (to
+            // accept input from any player) or a specific index. If we pass a null
+            // controlling player, the InputState helper returns to us which player
+            // actually provided the input. We pass that through to our Accepted and
+            // Cancelled events, so they can tell which player triggered them.
+            if (menuSelect.Evaluate(input, ControllingPlayer, out playerIndex))
+            {
+                // Raise the accepted event, then exit the message box.
+                if (Accepted != null)
+                    Accepted(this, new PlayerIndexEventArgs(playerIndex));
+
+                ExitScreen();
+            }
+            else if (menuCancel.Evaluate(input, ControllingPlayer, out playerIndex))
+            {
+                // Raise the cancelled event, then exit the message box.
+                if (Cancelled != null)
+                    Cancelled(this, new PlayerIndexEventArgs(playerIndex));
+
+                ExitScreen();
+            }
+        }
+
+
+        #endregion
+
+        #region Draw
+
+
+        /// <summary>
+        /// Draws the message box.
+        /// </summary>
+        public override void Draw(GameTime gameTime)
+        {
+            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
+            SpriteFont font = ScreenManager.Font;
+
+            // Darken down any other screens that were drawn beneath the popup.
+            ScreenManager.FadeBackBufferToBlack(TransitionAlpha * 2 / 3);
+
+            // 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);
+            Vector2 textPosition = (viewportSize - textSize) / 2;
+
+            // The background includes a border somewhat larger than the text itself.
+            const int hPad = 32;
+            const int vPad = 16;
+
+            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 = Color.White * TransitionAlpha;
+
+            spriteBatch.Begin();
+
+            // Draw the background rectangle.
+            spriteBatch.Draw(gradientTexture, backgroundRectangle, color);
+
+            // Draw the message box text.
+            spriteBatch.DrawString(font, message, textPosition, color);
+
+            spriteBatch.End();
+        }
+
+
+        #endregion
+    }
+}

+ 149 - 0
SampleCode/Screens/OptionsMenuScreen.cs

@@ -0,0 +1,149 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// OptionsMenuScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using Microsoft.Xna.Framework;
+#endregion
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// The options screen is brought up over the top of the main menu
+    /// screen, and gives the user a chance to configure the game
+    /// in various hopefully useful ways.
+    /// </summary>
+    class OptionsMenuScreen : MenuScreen
+    {
+        #region Fields
+
+        MenuEntry ungulateMenuEntry;
+        MenuEntry languageMenuEntry;
+        MenuEntry frobnicateMenuEntry;
+        MenuEntry elfMenuEntry;
+
+        enum Ungulate
+        {
+            BactrianCamel,
+            Dromedary,
+            Llama,
+        }
+
+        static Ungulate currentUngulate = Ungulate.Dromedary;
+
+        static string[] languages = { "C#", "French", "Deoxyribonucleic acid" };
+        static int currentLanguage = 0;
+
+        static bool frobnicate = true;
+
+        static int elf = 23;
+
+        #endregion
+
+        #region Initialization
+
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        public OptionsMenuScreen()
+            : base("Options")
+        {
+            // Create our menu entries.
+            ungulateMenuEntry = new MenuEntry(string.Empty);
+            languageMenuEntry = new MenuEntry(string.Empty);
+            frobnicateMenuEntry = new MenuEntry(string.Empty);
+            elfMenuEntry = new MenuEntry(string.Empty);
+
+            SetMenuEntryText();
+
+            MenuEntry back = new MenuEntry("Back");
+
+            // Hook up menu event handlers.
+            ungulateMenuEntry.Selected += UngulateMenuEntrySelected;
+            languageMenuEntry.Selected += LanguageMenuEntrySelected;
+            frobnicateMenuEntry.Selected += FrobnicateMenuEntrySelected;
+            elfMenuEntry.Selected += ElfMenuEntrySelected;
+            back.Selected += OnCancel;
+            
+            // Add entries to the menu.
+            MenuEntries.Add(ungulateMenuEntry);
+            MenuEntries.Add(languageMenuEntry);
+            MenuEntries.Add(frobnicateMenuEntry);
+            MenuEntries.Add(elfMenuEntry);
+            MenuEntries.Add(back);
+        }
+
+
+        /// <summary>
+        /// Fills in the latest values for the options screen menu text.
+        /// </summary>
+        void SetMenuEntryText()
+        {
+            ungulateMenuEntry.Text = "Preferred ungulate: " + currentUngulate;
+            languageMenuEntry.Text = "Language: " + languages[currentLanguage];
+            frobnicateMenuEntry.Text = "Frobnicate: " + (frobnicate ? "on" : "off");
+            elfMenuEntry.Text = "elf: " + elf;
+        }
+
+
+        #endregion
+
+        #region Handle Input
+
+
+        /// <summary>
+        /// Event handler for when the Ungulate menu entry is selected.
+        /// </summary>
+        void UngulateMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+        {
+            currentUngulate++;
+
+            if (currentUngulate > Ungulate.Llama)
+                currentUngulate = 0;
+
+            SetMenuEntryText();
+        }
+
+
+        /// <summary>
+        /// Event handler for when the Language menu entry is selected.
+        /// </summary>
+        void LanguageMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+        {
+            currentLanguage = (currentLanguage + 1) % languages.Length;
+
+            SetMenuEntryText();
+        }
+
+
+        /// <summary>
+        /// Event handler for when the Frobnicate menu entry is selected.
+        /// </summary>
+        void FrobnicateMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+        {
+            frobnicate = !frobnicate;
+
+            SetMenuEntryText();
+        }
+
+
+        /// <summary>
+        /// Event handler for when the Elf menu entry is selected.
+        /// </summary>
+        void ElfMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+        {
+            elf++;
+
+            SetMenuEntryText();
+        }
+
+
+        #endregion
+    }
+}

+ 79 - 0
SampleCode/Screens/PauseMenuScreen.cs

@@ -0,0 +1,79 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// PauseMenuScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using Microsoft.Xna.Framework;
+#endregion
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// The pause menu comes up over the top of the game,
+    /// giving the player options to resume or quit.
+    /// </summary>
+    class PauseMenuScreen : MenuScreen
+    {
+        #region Initialization
+
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        public PauseMenuScreen()
+            : base("Paused")
+        {
+            // Create our menu entries.
+            MenuEntry resumeGameMenuEntry = new MenuEntry("Resume Game");
+            MenuEntry quitGameMenuEntry = new MenuEntry("Quit Game");
+            
+            // Hook up menu event handlers.
+            resumeGameMenuEntry.Selected += OnCancel;
+            quitGameMenuEntry.Selected += QuitGameMenuEntrySelected;
+
+            // Add entries to the menu.
+            MenuEntries.Add(resumeGameMenuEntry);
+            MenuEntries.Add(quitGameMenuEntry);
+        }
+
+
+        #endregion
+
+        #region Handle Input
+
+
+        /// <summary>
+        /// Event handler for when the Quit Game menu entry is selected.
+        /// </summary>
+        void QuitGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+        {
+            const string message = "Are you sure you want to quit this game?";
+
+            MessageBoxScreen confirmQuitMessageBox = new MessageBoxScreen(message);
+
+            confirmQuitMessageBox.Accepted += ConfirmQuitMessageBoxAccepted;
+
+            ScreenManager.AddScreen(confirmQuitMessageBox, ControllingPlayer);
+        }
+
+
+        /// <summary>
+        /// Event handler for when the user selects ok on the "are you sure
+        /// you want to quit" message box. This uses the loading screen to
+        /// transition from the game back to the main menu screen.
+        /// </summary>
+        void ConfirmQuitMessageBoxAccepted(object sender, PlayerIndexEventArgs e)
+        {
+            LoadingScreen.Load(ScreenManager, false, null, new BackgroundScreen(),
+                                                           new MainMenuScreen());
+        }
+
+
+        #endregion
+    }
+}

+ 66 - 0
SampleCode/Screens/PhoneMainMenuScreen.cs

@@ -0,0 +1,66 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// PhoneMainMenuScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using Microsoft.Xna.Framework;
+using System;
+
+namespace GameStateManagementSample
+{
+    class PhoneMainMenuScreen : PhoneMenuScreen
+    {
+        public PhoneMainMenuScreen()
+            : base("Main Menu")
+        {
+            // Create a button to start the game
+            Button playButton = new Button("Play");
+            playButton.Tapped += playButton_Tapped;
+            MenuButtons.Add(playButton);
+
+            // Create two buttons to toggle sound effects and music. This sample just shows one way
+            // of making and using these buttons; it doesn't actually have sound effects or music
+            BooleanButton sfxButton = new BooleanButton("Sound Effects", true);
+            sfxButton.Tapped += sfxButton_Tapped;
+            MenuButtons.Add(sfxButton);
+
+            BooleanButton musicButton = new BooleanButton("Music", true);
+            musicButton.Tapped += musicButton_Tapped;
+            MenuButtons.Add(musicButton);
+        }
+
+        void playButton_Tapped(object sender, EventArgs e)
+        {
+            // When the "Play" button is tapped, we load the GameplayScreen
+            LoadingScreen.Load(ScreenManager, true, PlayerIndex.One, new GameplayScreen());
+        }
+
+        void sfxButton_Tapped(object sender, EventArgs e)
+        {
+            BooleanButton button = sender as BooleanButton;
+
+            // In a real game, you'd want to store away the value of 
+            // the button to turn off sounds here. :)
+        }
+
+        void musicButton_Tapped(object sender, EventArgs e)
+        {
+            BooleanButton button = sender as BooleanButton;
+
+            // In a real game, you'd want to store away the value of 
+            // the button to turn off music here. :)
+        }
+
+#if !__IOS__
+        protected override void OnCancel()
+        {
+            //ScreenManager.Game.Exit();
+            base.OnCancel();
+        }
+#endif
+    }
+}

+ 149 - 0
SampleCode/Screens/PhoneMenuScreen.cs

@@ -0,0 +1,149 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// PhoneMenuScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System;
+using System.Collections.Generic;
+using GameStateManagement;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using Microsoft.Xna.Framework.Input.Touch;
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// Provides a basic base screen for menus on Windows Phone leveraging the Button class.
+    /// </summary>
+    class PhoneMenuScreen : GameScreen
+    {
+        List<Button> menuButtons = new List<Button>();
+        string menuTitle;
+
+        InputAction menuCancel;
+
+        /// <summary>
+        /// Gets the list of buttons, so derived classes can add or change the menu contents.
+        /// </summary>
+        protected IList<Button> MenuButtons
+        {
+            get { return menuButtons; }
+        }
+
+        /// <summary>
+        /// Creates the PhoneMenuScreen with a particular title.
+        /// </summary>
+        /// <param name="title">The title of the screen</param>
+        public PhoneMenuScreen(string title)
+        {
+            menuTitle = title;
+
+            TransitionOnTime = TimeSpan.FromSeconds(0.5);
+            TransitionOffTime = TimeSpan.FromSeconds(0.5);
+
+            // Create the menuCancel action
+            menuCancel = new InputAction(new Buttons[] { Buttons.Back }, null, true);
+
+            // We need tap gestures to hit the buttons
+            EnabledGestures = GestureType.Tap;
+        }
+
+        public override void Activate(bool instancePreserved)
+        {
+            // When the screen is activated, we have a valid ScreenManager so we can arrange
+            // our buttons on the screen
+            float y = 140f;
+            float center = ScreenManager.GraphicsDevice.Viewport.Bounds.Center.X;
+            for (int i = 0; i < MenuButtons.Count; i++)
+            {
+                Button b = MenuButtons[i];
+
+                b.Position = new Vector2(center - b.Size.X / 2, y);
+                y += b.Size.Y * 1.5f;
+            }
+
+            base.Activate(instancePreserved);
+        }
+
+        public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
+        {
+            // Update opacity of the buttons
+            foreach (Button b in menuButtons)
+            {
+                b.Alpha = TransitionAlpha;
+            }
+
+            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
+        }
+
+        /// <summary>
+        /// An overrideable method called whenever the menuCancel action is triggered
+        /// </summary>
+        protected virtual void OnCancel() { }
+
+        public override void HandleInput(GameTime gameTime, InputState input)
+        {
+            // Test for the menuCancel action
+            PlayerIndex player;
+            if (menuCancel.Evaluate(input, ControllingPlayer, out player))
+            {
+                OnCancel();
+            }
+
+            // Read in our gestures
+            foreach (GestureSample gesture in input.Gestures)
+            {
+                // If we have a tap
+                if (gesture.GestureType == GestureType.Tap)
+                {
+                    // Test the tap against the buttons until one of the buttons handles the tap
+                    foreach (Button b in menuButtons)
+                    {
+                        if (b.HandleTap(gesture.Position))
+                            break;
+                    }
+                }
+            }
+
+            base.HandleInput(gameTime, input);
+        }
+
+        public override void Draw(GameTime gameTime)
+        {
+            GraphicsDevice graphics = ScreenManager.GraphicsDevice;
+            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
+            SpriteFont font = ScreenManager.Font;
+
+            spriteBatch.Begin();
+
+            // Draw all of the buttons
+            foreach (Button b in menuButtons)
+                b.Draw(this);
+
+            // Make the menu slide into place during transitions, using a
+            // power curve to make things look more interesting (this makes
+            // the movement slow down as it nears the end).
+            float transitionOffset = (float)Math.Pow(TransitionPosition, 2);
+
+            // Draw the menu title centered on the screen
+            Vector2 titlePosition = new Vector2(graphics.Viewport.Width / 2, 80);
+            Vector2 titleOrigin = font.MeasureString(menuTitle) / 2;
+            Color titleColor = new Color(192, 192, 192) * TransitionAlpha;
+            float titleScale = 1.25f;
+
+            titlePosition.Y -= transitionOffset * 100;
+
+            spriteBatch.DrawString(font, menuTitle, titlePosition, titleColor, 0, 
+                                   titleOrigin, titleScale, SpriteEffects.None, 0);
+
+            spriteBatch.End();
+
+            base.Draw(gameTime);
+        }
+    }
+}

+ 57 - 0
SampleCode/Screens/PhonePauseScreen.cs

@@ -0,0 +1,57 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// PhonePauseScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System;
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// A basic pause screen for Windows Phone
+    /// </summary>
+    class PhonePauseScreen : PhoneMenuScreen
+    {
+        public PhonePauseScreen()
+            : base("Paused")
+        {
+            // Create the "Resume" and "Exit" buttons for the screen
+
+            Button resumeButton = new Button("Resume");
+            resumeButton.Tapped += resumeButton_Tapped;
+            MenuButtons.Add(resumeButton);
+
+            Button exitButton = new Button("Exit");
+            exitButton.Tapped += exitButton_Tapped;
+            MenuButtons.Add(exitButton);
+        }
+
+        /// <summary>
+        /// The "Resume" button handler just calls the OnCancel method so that 
+        /// pressing the "Resume" button is the same as pressing the hardware back button.
+        /// </summary>
+        void resumeButton_Tapped(object sender, EventArgs e)
+        {
+            OnCancel();
+        }
+
+        /// <summary>
+        /// The "Exit" button handler uses the LoadingScreen to take the user out to the main menu.
+        /// </summary>
+        void exitButton_Tapped(object sender, EventArgs e)
+        {
+            LoadingScreen.Load(ScreenManager, false, null, new BackgroundScreen(),
+                                                           new PhoneMainMenuScreen());
+        }
+
+        protected override void OnCancel()
+        {
+            ExitScreen();
+            base.OnCancel();
+        }
+    }
+}

+ 42 - 0
SampleCode/Screens/PlayerIndexEventArgs.cs

@@ -0,0 +1,42 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// PlayerIndexEventArgs.cs
+//
+// XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using Microsoft.Xna.Framework;
+#endregion
+
+namespace GameStateManagementSample
+{
+    /// <summary>
+    /// Custom event argument which includes the index of the player who
+    /// triggered the event. This is used by the MenuEntry.Selected event.
+    /// </summary>
+    class PlayerIndexEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        public PlayerIndexEventArgs(PlayerIndex playerIndex)
+        {
+            this.playerIndex = playerIndex;
+        }
+
+
+        /// <summary>
+        /// Gets the index of the player who triggered this event.
+        /// </summary>
+        public PlayerIndex PlayerIndex
+        {
+            get { return playerIndex; }
+        }
+
+        PlayerIndex playerIndex;
+    }
+}