#region CPL License /* Nuclex Framework Copyright (C) 2002-2011 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.Collections.Generic; using System.IO; #if !XBOX360 using System.Security.Cryptography; using System.Text; #endif using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Content; using Nuclex.Graphics; namespace Nuclex.Game.Content { /// Content manager for loading content from in-memory arrays /// /// This is not much different from the resource content manager, since resources /// are always loaded into a process and are "in-memory" as well, but this /// content manager allows you to load content directly out of byte arrays. /// public class MemoryContentManager : ContentManager { /// /// Initializes a new embedded content manager using a directly specified /// graphics device service for the resources. /// /// /// Graphics device service to load the content asset in /// public MemoryContentManager(IGraphicsDeviceService graphicsDeviceService) : this( GraphicsDeviceServiceHelper.MakePrivateServiceProvider(graphicsDeviceService) ) { } /// /// Initializes a new embedded content manager using the provided game services /// container for providing services for the loaded asset. /// /// /// Service container containing the services the asset may access /// public MemoryContentManager(IServiceProvider services) : base(services) { } #if WINDOWS /// Loads the asset the embedded content manager was created for /// Type of the asset to load /// Content that will be loaded as an asset /// The loaded asset /// /// /// To mirror the behavior of the ResourceContentManager class, this method /// calculates the SHA-1 of the provided array. Otherwise, you could request /// the same asset two times and when you dispose one, the other requested /// instance would still work, which does not match the behavior of /// the ResourceContentManager. /// /// /// It is recommended that you use the named LoadAsset method or control /// asset lifetimes yourself by using the ReadAsset() method. /// /// public AssetType Load(byte[] content) { return Load(content, getSha1(content)); } #endif /// Loads the asset the embedded content manager was created for /// Type of the asset to load /// Content that will be loaded as an asset /// Unique name of the resource /// The loaded asset /// /// This class avoids the SHA-1 calculation under the promise that the caller /// will provide a name that is unique for each loaded asset. /// public AssetType Load(byte[] content, string uniqueName) { lock(this) { this.content = content; try { return base.Load(uniqueName); } finally { if(this.memoryStream != null) { this.memoryStream.Dispose(); this.memoryStream = null; } this.content = null; } } // lock(this) } /// Loads an asset from the provided byte array /// Type of the asset to load /// Content that will be loaded as an asset /// The loaded asset public AssetType ReadAsset(byte[] content) { lock(this) { using(this.memoryStream = new MemoryStream(content, false)) { return base.ReadAsset("null", null); } } // lock(this) } /// Opens a stream for reading the specified asset /// The name of the asset to be read /// The opened stream for the asset protected override Stream OpenStream(string assetName) { if(this.memoryStream == null) { this.memoryStream = new MemoryStream(this.content, false); } return this.memoryStream; } #if WINDOWS /// Calculates the SHA-1 hash of the provided byte array /// Data that will be hashed /// A string containing the SHA-1 sum of the byte array private string getSha1(byte[] data) { if(this.sha1HashProvider == null) { this.sha1HashProvider = SHA1.Create(); } byte[] hashCode = this.sha1HashProvider.ComputeHash(data); StringBuilder builder = new StringBuilder(hashCode.Length * 2); for(int index = 0; index < hashCode.Length; ++index) { builder.AppendFormat("{0:x2}", hashCode[index]); } return builder.ToString(); } #endif /// Content that will be loaded by the embedded content manager private MemoryStream memoryStream; /// Content which is currently being loaded private byte[] content; #if WINDOWS /// /// SHA-1 hash provider used to calculate SHA-1 sums of asset data /// private SHA1 sha1HashProvider; #endif } } // namespace Nuclex.Game.Content