Skip to content

Instantly share code, notes, and snippets.

@geirsagberg
Last active January 29, 2020 19:50
Show Gist options
  • Save geirsagberg/b86622872f027843a50f1e6a8c083cdd to your computer and use it in GitHub Desktop.
Save geirsagberg/b86622872f027843a50f1e6a8c083cdd to your computer and use it in GitHub Desktop.
Generate strongly typed MonoGame resources
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace BunnyLand.ResourceGenerator
{
public static class Generator
{
public static void WriteSongs(string contentPath, TextWriter textWriter)
{
Write(contentPath, textWriter, "Songs", "mp3", "Song", "Microsoft.Xna.Framework.Media");
}
public static void WriteSpriteFonts(string contentPath, TextWriter textWriter)
{
Write(contentPath, textWriter, "SpriteFonts", "spritefont", "SpriteFont",
"Microsoft.Xna.Framework.Graphics");
}
public static void WriteTextures(string contentPath, TextWriter textWriter)
{
Write(contentPath, textWriter, "Textures", "png", "Texture2D", "Microsoft.Xna.Framework.Graphics");
}
public static void WriteSoundEffects(string contentPath, TextWriter textWriter)
{
Write(contentPath, textWriter, "SoundEffects", "wav", "SoundEffect", "Microsoft.Xna.Framework.Audio");
}
private static void Write(string contentPath, TextWriter textWriter, string className, string extension,
string propertyType, params string[] namespaces)
{
if (textWriter == null) throw new ArgumentNullException(nameof(textWriter));
textWriter.Write($@"// <auto-generated />
// ReSharper disable All
using System.ComponentModel;
using Microsoft.Xna.Framework.Content;
{string.Join(Environment.NewLine, namespaces.Select(ns => $"using {ns};"))}
namespace BunnyLand.DesktopGL.Resources
{{
public partial class {className} : ResourcesBase<{propertyType}>
{{
public {className}(ContentManager contentManager) : base(contentManager)
{{
}}
");
var enumerationOptions = new EnumerationOptions {
RecurseSubdirectories = true
};
foreach (var path in Directory.EnumerateFiles(contentPath, $"*.{extension}", enumerationOptions)) {
textWriter.Write($@"
[Description(""{FilePathToRelativePath(path, extension)}"")]
public {propertyType} {FilePathToPropertyName(path, extension)} {{ get; set; }}");
}
textWriter.Write(@"
}
}
");
}
private static string FilePathToRelativePath(string path, string extension)
{
return path.Replace("\\", "/", StringComparison.OrdinalIgnoreCase).Split("Content/").Last()
.Replace($".{extension}", "", StringComparison.OrdinalIgnoreCase);
}
private static readonly Regex InvalidPropertyNameRegex = new Regex("[^a-zA-Z0-9]");
private static string FilePathToPropertyName(string path, string extension)
{
var fileName = new FileInfo(path).Name.Replace($".{extension}", "", StringComparison.OrdinalIgnoreCase);
var propertyName = InvalidPropertyNameRegex.Replace(fileName, "");
return propertyName;
}
}
}
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using Microsoft.Xna.Framework.Content;
namespace BunnyLand.DesktopGL.Resources
{
public abstract class ResourcesBase<T>
{
protected readonly ContentManager ContentManager;
protected ResourcesBase(ContentManager contentManager)
{
ContentManager = contentManager;
}
public void Load()
{
foreach (var propertyInfo in GetType().GetProperties().Where(p => p.PropertyType == typeof(T))) {
var file = propertyInfo.GetCustomAttribute<DescriptionAttribute>()?.Description;
if (file != null) {
var texture = ContentManager.Load<T>(file);
propertyInfo.SetValue(this, texture);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment