<#@ template language="C#" hostSpecific="true" #> <#@ assembly name="System.Core.dll" #> <#@ assembly name="System.dll" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Globalization" #> <#@ import namespace="System.Text.RegularExpressions" #> namespace Nez { public static class Content { public static class Nez { <# PrintNezContent(); #> } public static class Audio { <# PrintAudio(); #> } public static class Fonts { <# PrintFonts(); #> } public static class Materials { <# PrintMaterials(); #> } public static class Particles { <# PrintParticles(); #> } public static class Shaders { <# PrintShaders(); #> } public static class Tilemaps { <# PrintTilemaps(); #> } public static class Textures { <# PrintTextures(); #> } public static class Atlases { <# PrintAtlases(); #> } public static class Compiled { <# PrintCompiledContent(); #> } } } <#+ // all the valid file extensions we should copy for each root folder private string[] validAudioExtensions = new string[] { ".ogg", ".wav" }; private string[] validFontExtensions = new string[] { ".fnt" }; private string[] validMaterialExtensions = new string[] { ".mat" }; private string[] validParticleExtensions = new string[] { ".pex" }; private string[] validShaderExtensions = new string[] { ".fxb" }; private string[] validTilemapExtensions = new string[] { ".tmx" }; private string[] validTextureExtensions = new string[] { ".png", ".jpg" }; private string[] validAtlasExtensions = new string[] { ".atlas" }; // C# reserved keywords private System.Collections.Generic.List keywords = new System.Collections.Generic.List { "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while" }; void PrintNezContent() { PrintSpecialFolderAndSubfolders("../Nez/DefaultContent", new string[] { ".xnb", ".fxb" }, true); } void PrintAudio() { PrintSpecialFolderAndSubfolders("Content/Audio", validAudioExtensions); } void PrintFonts() { PrintSpecialFolderAndSubfolders("Content/Fonts", validFontExtensions); } void PrintMaterials() { PrintSpecialFolderAndSubfolders("Content/Materials", validMaterialExtensions); } void PrintParticles() { PrintSpecialFolderAndSubfolders("Content/Particles", validParticleExtensions); } void PrintShaders() { PrintSpecialFolderAndSubfolders("Content/Shaders", validShaderExtensions); } void PrintTextures() { PrintSpecialFolderAndSubfolders("Content/Textures", validTextureExtensions); } void PrintAtlases() { PrintSpecialFolderAndSubfolders("Content/Atlases", validAtlasExtensions); } void PrintTilemaps() { PrintSpecialFolderAndSubfolders("Content/Tilemaps", validTilemapExtensions); } void PrintCompiledContent() { PrintSpecialFolderAndSubfolders("CompiledContent/bin/DesktopGL", new string[] { ".xnb" }, true); } void PrintSpecialFolderAndSubfolders(string source, string[] validExtensions, bool isCompiledFolder = false) { if (!Directory.Exists(source)) return; var stripPath = isCompiledFolder ? source : ""; PrintContentFiles(source, 3, stripPath, validExtensions); // loop through all the directories in our sourceFolder foreach (var dir in Directory.GetDirectories(source)) { var dirName = new DirectoryInfo(dir).Name.ToLower(); PrintDirectoryClass(dir, 3, stripPath, validExtensions, isCompiledFolder); } } // recursively creates a class for each directory void PrintDirectoryClass(string dir, int depth, string sourceFolder, string[] validFileExtensions, bool isCompiledFolder) { var dirInfo = new DirectoryInfo(dir); var firstIndent = new string(' ', depth * 4); var className = GenerateClassName(dirInfo.Name, true); if (!FolderHasContent(dir, validFileExtensions)) return; // fix our class name if this is the FNAEffects folder if (dir.Contains("Nez/DefaultContent") && className == "FNAEffects") className = "Effects"; WriteLine("{0}public static class {1}\n{2}{{", firstIndent, className, firstIndent); // handle subdirectories foreach (var subdir in Directory.GetDirectories(dir)) PrintDirectoryClass(subdir, depth + 1, sourceFolder, validFileExtensions, isCompiledFolder); // handle files PrintContentFiles(dir, depth + 1, sourceFolder, validFileExtensions); WriteLine("{0}}}\n", firstIndent); } // prints a const string for each file in the directory void PrintContentFiles(string dir, int depth, string sourceFolder, string[] validFileExtensions) { var firstIndent = new string('\t', depth); var files = Directory.EnumerateFiles(dir) .Where( s => Array.IndexOf(validFileExtensions, Path.GetExtension(s)) >= 0); foreach (var file in files) { // clear out all of the path up to the sourceFolder so we get just the relative path to the Content folder var finalPath = file.Substring(file.IndexOf(sourceFolder) + sourceFolder.Length); var fileInfo = new FileInfo(file); var fileName = fileInfo.Name; // clean the extension foreach (var extension in validFileExtensions) fileName = fileName.Replace(extension, string.Empty); var className = GenerateClassName(fileName, false); if (finalPath[0] == '/' || finalPath[0] == '\\') finalPath = finalPath.Substring(1); // remove xnb extensions to avoid issues with loading finalPath = finalPath.Replace(".xnb", string.Empty); // deal with built-in Nez content pathing if (dir.Contains("Nez/DefaultContent")) { if (dir.Contains("FNAEffects")) { finalPath = finalPath.Replace("FNAEffects", "Effects"); finalPath = "Content/Nez/" + finalPath; } else if(dir.Contains("Textures")) { finalPath = "Nez/" + finalPath; } } // if file name is reserved insert a leading '@' if (keywords.Contains(className)) className = className.Insert( 0, "@" ); WriteLine("{0}public const string {1} = @\"{2}\";", firstIndent, className, finalPath); } if (files.Count() > 0) WriteLine(""); } // attempts to generate a proper path name string GenerateClassName(string className, bool uppercaseFirstChar) { // handle upper or lower casing the first char in the className if (uppercaseFirstChar && char.IsLower(className[0])) className = char.ToUpper(className[0]) + className.Substring(1); className = className.Replace("-", "_"); // remove invalid characters var regex = new Regex(@"[^\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Nl}\p{Mn}\p{Mc}\p{Cf}\p{Pc}\p{Lm}]"); className = regex.Replace(className, ""); // class name doesn't begin with a letter, insert an underscore if (!char.IsLetter(className, 0)) className = className.Insert(0, "_"); return className.Replace(" ", string.Empty); } // returns true if the folder or any subfolder has some content with a valid file extension bool FolderHasContent(string dir, string[] validFileExtensions) { var files = Directory.EnumerateFiles(dir) .Where( s => Array.IndexOf(validFileExtensions, Path.GetExtension(s)) >= 0); return files.Count() > 0; } #>