From 99d286d8344eed2ef67c67c521a339f8457b3cd7 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Wed, 22 Apr 2020 00:30:55 +0200 Subject: [PATCH] raw content manager --- MLEM/Content/RawContentManager.cs | 76 +++++++++++++++++++++++++++++++ MLEM/Content/RawContentReader.cs | 28 ++++++++++++ MLEM/Content/SongReader.cs | 17 +++++++ MLEM/Content/SoundEffectReader.cs | 16 +++++++ MLEM/Content/Texture2DReader.cs | 21 +++++++++ Sandbox/Content/Content.mgcb | 12 ----- Sandbox/GameImpl.cs | 6 ++- Sandbox/Sandbox.csproj | 4 +- 8 files changed, 166 insertions(+), 14 deletions(-) create mode 100644 MLEM/Content/RawContentManager.cs create mode 100644 MLEM/Content/RawContentReader.cs create mode 100644 MLEM/Content/SongReader.cs create mode 100644 MLEM/Content/SoundEffectReader.cs create mode 100644 MLEM/Content/Texture2DReader.cs diff --git a/MLEM/Content/RawContentManager.cs b/MLEM/Content/RawContentManager.cs new file mode 100644 index 0000000..2255d8d --- /dev/null +++ b/MLEM/Content/RawContentManager.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; + +namespace MLEM.Content { + public class RawContentManager : ContentManager, IGameComponent { + + private static readonly RawContentReader[] Readers = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(a => a.GetExportedTypes()) + .Where(t => t.IsSubclassOf(typeof(RawContentReader)) && !t.IsAbstract) + .Select(t => t.GetConstructor(Type.EmptyTypes).Invoke(null)) + .Cast().ToArray(); + + private readonly List disposableAssets = new List(); + + public readonly GraphicsDevice GraphicsDevice; + + public RawContentManager(IServiceProvider serviceProvider, string rootDirectory = "Content") : + base(serviceProvider, rootDirectory) { + if (serviceProvider.GetService(typeof(IGraphicsDeviceService)) is IGraphicsDeviceService s) + this.GraphicsDevice = s.GraphicsDevice; + } + + public override T Load(string assetName) { + if (this.LoadedAssets.TryGetValue(assetName, out var ret) && ret is T t) + return t; + return this.Read(assetName, default); + } + + private static RawContentReader GetReader() { + var reader = Readers.FirstOrDefault(r => r.CanRead(typeof(T))); + if (reader == null) + throw new ContentLoadException($"{typeof(T)} has no RawContentReader"); + return reader; + } + + protected override void ReloadAsset(string originalAssetName, T currentAsset) { + this.Read(originalAssetName, currentAsset); + } + + private T Read(string assetName, T existing) { + var reader = GetReader(); + foreach (var ext in reader.GetFileExtensions()) { + var file = new FileInfo(Path.Combine(this.RootDirectory, $"{assetName}.{ext}")); + if (!file.Exists) + continue; + using (var stream = file.OpenRead()) { + var read = reader.Read(this, assetName, stream, existing); + if (!(read is T t)) + throw new ContentLoadException($"{reader} returned non-{typeof(T)} for asset {assetName}"); + this.LoadedAssets[assetName] = t; + if (t is IDisposable d) + this.disposableAssets.Add(d); + return t; + } + } + throw new ContentLoadException($"Asset {assetName} not found"); + } + + public override void Unload() { + foreach (var d in this.disposableAssets) + d.Dispose(); + this.disposableAssets.Clear(); + base.Unload(); + } + + public void Initialize() { + } + + } +} \ No newline at end of file diff --git a/MLEM/Content/RawContentReader.cs b/MLEM/Content/RawContentReader.cs new file mode 100644 index 0000000..82e31aa --- /dev/null +++ b/MLEM/Content/RawContentReader.cs @@ -0,0 +1,28 @@ +using System; +using System.IO; + +namespace MLEM.Content { + public abstract class RawContentReader { + + public abstract bool CanRead(Type t); + + public abstract object Read(RawContentManager manager, string assetPath, Stream stream, object existing); + + public abstract string[] GetFileExtensions(); + + } + + public abstract class RawContentReader : RawContentReader { + + public override bool CanRead(Type t) { + return typeof(T).IsAssignableFrom(t); + } + + public override object Read(RawContentManager manager, string assetPath, Stream stream, object existing) { + return this.Read(manager, assetPath, stream, (T) existing); + } + + protected abstract T Read(RawContentManager manager, string assetPath, Stream stream, T existing); + + } +} \ No newline at end of file diff --git a/MLEM/Content/SongReader.cs b/MLEM/Content/SongReader.cs new file mode 100644 index 0000000..4576068 --- /dev/null +++ b/MLEM/Content/SongReader.cs @@ -0,0 +1,17 @@ +using System; +using System.IO; +using Microsoft.Xna.Framework.Media; + +namespace MLEM.Content { + public class SongReader : RawContentReader { + + protected override Song Read(RawContentManager manager, string assetPath, Stream stream, Song existing) { + return Song.FromUri(Path.GetFileNameWithoutExtension(assetPath), new Uri(assetPath)); + } + + public override string[] GetFileExtensions() { + return new[] {"ogg", "wav", "mp3"}; + } + + } +} \ No newline at end of file diff --git a/MLEM/Content/SoundEffectReader.cs b/MLEM/Content/SoundEffectReader.cs new file mode 100644 index 0000000..a5ca9d2 --- /dev/null +++ b/MLEM/Content/SoundEffectReader.cs @@ -0,0 +1,16 @@ +using System.IO; +using Microsoft.Xna.Framework.Audio; + +namespace MLEM.Content { + public class SoundEffectReader : RawContentReader { + + protected override SoundEffect Read(RawContentManager manager, string assetPath, Stream stream, SoundEffect existing) { + return SoundEffect.FromStream(stream); + } + + public override string[] GetFileExtensions() { + return new[] {"ogg", "wav", "mp3"}; + } + + } +} \ No newline at end of file diff --git a/MLEM/Content/Texture2DReader.cs b/MLEM/Content/Texture2DReader.cs new file mode 100644 index 0000000..391b79e --- /dev/null +++ b/MLEM/Content/Texture2DReader.cs @@ -0,0 +1,21 @@ +using System.IO; +using Microsoft.Xna.Framework.Graphics; + +namespace MLEM.Content { + public class Texture2DReader : RawContentReader { + + protected override Texture2D Read(RawContentManager manager, string assetPath, Stream stream, Texture2D existing) { + if (existing != null) { + existing.Reload(stream); + return existing; + } else { + return Texture2D.FromStream(manager.GraphicsDevice, stream); + } + } + + public override string[] GetFileExtensions() { + return new[] {"png", "bmp", "gif", "jpg", "tif", "dds"}; + } + + } +} \ No newline at end of file diff --git a/Sandbox/Content/Content.mgcb b/Sandbox/Content/Content.mgcb index 42a56b3..f637798 100644 --- a/Sandbox/Content/Content.mgcb +++ b/Sandbox/Content/Content.mgcb @@ -24,18 +24,6 @@ #begin Test.json /copy:Test.json -#begin Textures/Test.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:Textures/Test.png - #begin Tiled/Map.tmx /importer:TiledMapImporter /processor:TiledMapProcessor diff --git a/Sandbox/GameImpl.cs b/Sandbox/GameImpl.cs index 1e722f1..5d7a865 100644 --- a/Sandbox/GameImpl.cs +++ b/Sandbox/GameImpl.cs @@ -4,6 +4,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using MLEM.Cameras; +using MLEM.Content; using MLEM.Data; using MLEM.Extended.Extensions; using MLEM.Extended.Tiled; @@ -27,6 +28,7 @@ namespace Sandbox { private TiledMap map; private IndividualTiledMapRenderer mapRenderer; private TiledMapCollisions collisions; + private RawContentManager rawContent; public GameImpl() { this.IsMouseVisible = true; @@ -38,6 +40,8 @@ namespace Sandbox { protected override void LoadContent() { base.LoadContent(); + this.Components.Add(this.rawContent = new RawContentManager(this.Services)); + this.map = LoadContent("Tiled/Map"); this.mapRenderer = new IndividualTiledMapRenderer(this.map); this.collisions = new TiledMapCollisions(this.map); @@ -50,7 +54,7 @@ namespace Sandbox { MaxScale = 4 }; - var tex = LoadContent("Textures/Test"); + var tex = this.rawContent.Load("Textures/Test"); var font = new GenericSpriteFont(LoadContent("Fonts/TestFont")); this.UiSystem.Style = new UntexturedStyle(this.SpriteBatch) { Font = font, diff --git a/Sandbox/Sandbox.csproj b/Sandbox/Sandbox.csproj index db72943..45565c1 100644 --- a/Sandbox/Sandbox.csproj +++ b/Sandbox/Sandbox.csproj @@ -22,7 +22,9 @@ - + + PreserveNewest +