/// <summary> /// This method loads a serialized data object /// from the StorageContainer for this game. /// </summary> public static void LoadScene() { // If a save is pending, save as soon as the storage device is chosen. IAsyncResult result = StorageDevice.BeginShowSelector(PlayerIndex.One, null, null); result.AsyncWaitHandle.WaitOne(); StorageDevice device = StorageDevice.EndShowSelector(result); // Open a storage container. result = device.BeginOpenContainer("StorageDemo", null, null); // Wait for the WaitHandle to become signaled. result.AsyncWaitHandle.WaitOne(); StorageContainer container = device.EndOpenContainer(result); // Close the wait handle. result.AsyncWaitHandle.Close(); string filename = "savegame.sav"; // Check to see whether the save exists. if (!container.FileExists(filename)) { // If not, dispose of the container and return. container.Dispose(); return; } // Open the file. Stream stream = container.OpenFile(filename, FileMode.Open); // Read the data from the file. XmlSerializer serializer = new XmlSerializer(typeof(SceneData)); SceneData data = (SceneData)serializer.Deserialize(stream); // Close the file. stream.Close(); // Dispose the container. container.Dispose(); LoadSaveData(data); }
} // GetSerializableProperties #endregion #region Save Scene public static void SaveScene() { // If a save is pending, save as soon as the storage device is chosen. IAsyncResult result = StorageDevice.BeginShowSelector(PlayerIndex.One, null, null); result.AsyncWaitHandle.WaitOne(); StorageDevice device = StorageDevice.EndShowSelector(result); // Create the data to save. SceneData data = CreateSaveData(); // Open a storage container. result = device.BeginOpenContainer("StorageDemo", null, null); // Wait for the WaitHandle to become signaled. result.AsyncWaitHandle.WaitOne(); StorageContainer container = device.EndOpenContainer(result); // Close the wait handle. result.AsyncWaitHandle.Close(); string filename = "savegame.sav"; // Check to see whether the save exists. if (container.FileExists(filename)) // Delete it so that we can create one fresh. container.DeleteFile(filename); // Create the file. Stream stream = container.CreateFile(filename); // Convert the object to XML data and put it in the stream. XmlSerializer serializer = new XmlSerializer(typeof(SceneData)); serializer.Serialize(stream, data); // Close the file. stream.Close(); // Dispose the container, to commit changes. container.Dispose(); } // Save Scene
} // CreateSaveData #endregion #region Load Save Data /// <summary> /// Create the structure that will be serialized. /// It stores content managers, assets and game objects. /// </summary> private static void LoadSaveData(SceneData sceneData) { // Generate content managers data. foreach (var contentManagerData in sceneData.ContentManagersData) { // Create Content Manager AssetContentManager contentManager = new AssetContentManager { Name = contentManagerData.Name }; foreach (var assetId in contentManagerData.AssetsId) { // The not resourced assets are already created and can change the content manager without recreation. foreach (var assetsWithoutResourceData in sceneData.AssetsWithoutResourceData) { if (assetId == assetsWithoutResourceData.Id) { assetsWithoutResourceData.Asset.ChangeContentManager(contentManager); break; } } } } // Recreate game objects (and the transform component) foreach (var gameObjectData in sceneData.GameObjectData) { GameObject gameObject; if (gameObjectData.is3D) { gameObject = new GameObject3D(); ((GameObject3D)gameObject).Transform.LocalMatrix = gameObjectData.LocalMatrix; } else { gameObject = new GameObject2D(); ((GameObject2D)gameObject).Transform.LocalMatrix = gameObjectData.LocalMatrix; } gameObject.Name = gameObjectData.Name; gameObject.Layer = Layer.GetLayerByNumber(gameObjectData.LayerNumber); gameObject.Active = gameObjectData.Active; gameObjectData.NewGameObject = gameObject; // Use to recreate the hierarchy. foreach (var componentData in gameObjectData.ComponentData) { // Create the component. // Reflection is needed because we can't know the type in compiler time and I don't want to use an inflexible big switch sentence. gameObject.GetType().GetMethod("AddComponent").MakeGenericMethod(componentData.Component.GetType()).Invoke(gameObject, null); // Each serializable property will be copy to the new component. PropertyInfo componentProperty = gameObject.GetType().GetProperty(componentData.Component.GetType().Name); List<PropertyInfo> propertiesName = GetSerializableProperties(componentData.Component.GetType()); for (int i = 0; i < propertiesName.Count; i++) { var property = propertiesName[i]; Component component = (Component) componentProperty.GetValue(gameObject, null); Object value = property.GetValue(componentData.Component, null); property.SetValue(component, value, null); } } } // Recreate hierarchy. foreach (var gameObjectData in sceneData.GameObjectData) { // If it is has a parent. if (gameObjectData.ParentId != long.MaxValue) { // Search all loaded game objects foreach (var searchedGameObjectData in sceneData.GameObjectData) { if (searchedGameObjectData.Id == gameObjectData.ParentId) { if (gameObjectData.is3D) ((GameObject3D)gameObjectData.NewGameObject).Parent = (GameObject3D)searchedGameObjectData.NewGameObject; else ((GameObject2D)gameObjectData.NewGameObject).Parent = (GameObject2D)searchedGameObjectData.NewGameObject; break; } } } } } // CreateSaveData
/// <summary> /// Create the structure that will be serialized. /// It stores content managers, assets and game objects. /// </summary> private static SceneData CreateSaveData() { SceneData sceneData = new SceneData(); #region Content Managers // Save content managers data. foreach (var contentManager in AssetContentManager.SortedContentManagers) { // Hidden content managers are ignored. // They carried information only useful for the system to work. // Next time you load the scene this information will be (possible) already loaded. if (!contentManager.Hidden) { ContentManagerData contentManagerData = new ContentManagerData(); contentManagerData.Id = contentManager.Id; contentManagerData.Name = contentManager.Name; foreach (var asset in contentManager.Assets) { contentManagerData.AssetsId.Add(asset.Id); } sceneData.ContentManagersData.Add(contentManagerData); } } #endregion #region Assets // Save assets data. foreach (var asset in Asset.SortedLoadedAssets) { // Hidden assets are ignored. // They carried information only useful for the system to work. // Next time you load the scene this information will be (possible) already loaded. if (!asset.Hidden) { if (asset is AssetWithoutResource) { AssetWithoutResourceData assetData = new AssetWithoutResourceData { Id = asset.Id, Asset = (AssetWithoutResource)asset, }; if (asset is AmbientLight) { if (((AmbientLight)asset).AmbientOcclusion != null) { assetData.InternalAssetsId.Add(((AmbientLight) asset).AmbientOcclusion.Id); assetData.InternalAssetPropertyNames.Add("AmbientOcclusion"); } } sceneData.AssetsWithoutResourceData.Add(assetData); } } } #endregion #region Game Objects // Save content managers data. foreach (var gameObject in GameObject.GameObjects) { // Hidden content managers are ignored. // They carried information only useful for the system to work. // Next time you load the scene this information will be (possible) already loaded. if (gameObject.Layer.Number != 31 && gameObject.Layer.Number != 30) { GameObjectData gameObjectData = new GameObjectData { Id = gameObject.Id, Name = gameObject.Name, is3D = gameObject is GameObject3D, Active = gameObject.Active, LayerNumber = gameObject.Layer.Number }; // Parent if (gameObject is GameObject3D) { gameObjectData.ParentId = ((GameObject3D)gameObject).Parent != null ? ((GameObject3D) gameObject).Parent.Id : long.MaxValue; gameObjectData.LocalMatrix = ((GameObject3D)gameObject).Transform.LocalMatrix; } else { gameObjectData.ParentId = ((GameObject2D)gameObject).Parent != null ? ((GameObject2D)gameObject).Parent.Id : long.MaxValue; gameObjectData.LocalMatrix = ((GameObject2D)gameObject).Transform.LocalMatrix; } // Components foreach (var component in gameObject.Components) { ComponentData componentData = new ComponentData { Id = component.Id, Component = component }; gameObjectData.ComponentData.Add(componentData); } sceneData.GameObjectData.Add(gameObjectData); } } #endregion return sceneData; } // CreateSaveData