mirror of
https://github.com/prime31/FNA-VSCode-Template.git
synced 2025-10-31 21:50:44 +07:00
T4 template processing task added
This commit is contained in:
parent
3952da3a60
commit
4e5f94d27a
@ -21,7 +21,9 @@ Start new FNA projects with Nez quickly and easily with handy setup scripts, a v
|
|||||||
2. Run `./getFNA.sh` (macOS) to download the latest Nez, FNA and fnalibs to the directory. You can run this script again if you want to update either FNA or the fnalibs at a later point. Nez is setup as a submodule so you can update it in the normal fashion.
|
2. Run `./getFNA.sh` (macOS) to download the latest Nez, FNA and fnalibs to the directory. You can run this script again if you want to update either FNA or the fnalibs at a later point. Nez is setup as a submodule so you can update it in the normal fashion.
|
||||||
3. Open the newly-created and named `PROJECT_NAME_YOU_CHOSE.code-workspace` file (or open the project folder in Visual Studio Code or the top-level sln in Visual Studio)
|
3. Open the newly-created and named `PROJECT_NAME_YOU_CHOSE.code-workspace` file (or open the project folder in Visual Studio Code or the top-level sln in Visual Studio)
|
||||||
|
|
||||||
That's it! Now you're ready to build and run the base project! When developing raw content (files not processed by the Pipeline tool) should be placed in the `Content` folder and anything that needs processing should go in the `CompiledContent` folder and added to the Pipeline tool.
|
That's it! Now you're ready to build and run the base project. When developing raw content (files not processed by the Pipeline tool) should be placed in the `Content` folder and anything that needs processing should go in the `CompiledContent` folder and added to the Pipeline tool.
|
||||||
|
|
||||||
|
If you want to see the output of `Debug.*` calls in the VS Code Debug Console, you have to install a listener by adding this somewhere in your code (Game1 is a good spot): `System.Diagnostics.Debug.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(System.Console.Out));`
|
||||||
|
|
||||||
|
|
||||||
## Build Tasks ##
|
## Build Tasks ##
|
||||||
@ -33,6 +35,7 @@ That's it! Now you're ready to build and run the base project! When developing r
|
|||||||
- **Build Content:** Runs good old MGCB.exe on the Content.mgcb file
|
- **Build Content:** Runs good old MGCB.exe on the Content.mgcb file
|
||||||
- **Force Build Content:** Force builds the content (MGCB.exe -r)
|
- **Force Build Content:** Force builds the content (MGCB.exe -r)
|
||||||
- **Open Pipeline Tool:** Opens the MonoGame Pipeline tool
|
- **Open Pipeline Tool:** Opens the MonoGame Pipeline tool
|
||||||
|
- **Process T4 Templates:** Processes any T4 templates found in the `T4Templates` folder. Note that the install script will attempt to install the t4 command line program which requires the `dotnet` command line program to be installed. The install command it will run is `dotnet tool install -g dotnet-t4`.
|
||||||
|
|
||||||
|
|
||||||
## License and Credits ##
|
## License and Credits ##
|
||||||
|
|||||||
@ -94,6 +94,10 @@ if [[ $shouldDownloadLibs =~ ^[Yy]$ ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# install t4 engine
|
||||||
|
dotnet tool install -g dotnet-t4
|
||||||
|
|
||||||
|
|
||||||
# Rename project
|
# Rename project
|
||||||
read -p "Enter the project name to use for your folder and csproj file or 'exit' to quit: " newProjectName
|
read -p "Enter the project name to use for your folder and csproj file or 'exit' to quit: " newProjectName
|
||||||
if [[ $newProjectName = 'exit' ]]; then
|
if [[ $newProjectName = 'exit' ]]; then
|
||||||
|
|||||||
16
project_name/.vscode/processT4Templates.sh
vendored
Executable file
16
project_name/.vscode/processT4Templates.sh
vendored
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# buildEffects
|
||||||
|
# Compiles all .fx files found in the project's Content directory.
|
||||||
|
# Intended for usage with VS Code Build Tasks tooling.
|
||||||
|
# You may need to change the path to fxc.exe depending on your installation.
|
||||||
|
|
||||||
|
printf "Starting T4 processing...\n"
|
||||||
|
|
||||||
|
for file in `find ./T4Templates/** -name "*.tt"` ;
|
||||||
|
do
|
||||||
|
# Build the template
|
||||||
|
t4 -r=System.dll -r=mscorlib.dll -r=netstandard.dll -r=System.IO.FileSystem.dll -r=System.Linq.dll -r=System.Text.RegularExpressions.dll `dirname $file`/`basename $file` -o `dirname $file`/Output/`basename $file .tt`.cs
|
||||||
|
|
||||||
|
echo "Built `basename $file`"
|
||||||
|
|
||||||
|
done
|
||||||
8
project_name/.vscode/tasks.json
vendored
8
project_name/.vscode/tasks.json
vendored
@ -120,5 +120,13 @@
|
|||||||
"command": "export MONOGAME_PIPELINE_PROJECT=${workspaceFolder}/CompiledContent/Content.mgcb && /Applications/Pipeline.app/Contents/MacOS/Pipeline",
|
"command": "export MONOGAME_PIPELINE_PROJECT=${workspaceFolder}/CompiledContent/Content.mgcb && /Applications/Pipeline.app/Contents/MacOS/Pipeline",
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"label": "Process T4 Templates",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "${workspaceFolder}/.vscode/processT4Templates.sh",
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": "$msCompile",
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
141
project_name/T4Templates/ContentPathGenerator.tt
Normal file
141
project_name/T4Templates/ContentPathGenerator.tt
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<#@ 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" #>
|
||||||
|
|
||||||
|
<# var sourceFolders = new string[] { "CompiledContent/bin/DesktopGL", "Content" }; #>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Nez
|
||||||
|
{
|
||||||
|
class Content
|
||||||
|
{
|
||||||
|
<#
|
||||||
|
|
||||||
|
// loop through all of our sourceFolders
|
||||||
|
foreach( var sourceFolder in sourceFolders )
|
||||||
|
{
|
||||||
|
var directories = Directory.GetDirectories( sourceFolder );
|
||||||
|
// loop through all the directories in our sourceFolder
|
||||||
|
foreach( var dir in directories )
|
||||||
|
{
|
||||||
|
var dirName = new DirectoryInfo( dir ).Name.ToLower();
|
||||||
|
if( dirName == "bin" || dirName == "obj" || dirName == "content" )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// dont delve into directories that don't contan xnb files
|
||||||
|
var xnbFiles = Directory.GetFiles( dir, "*.xnb", SearchOption.AllDirectories );
|
||||||
|
if( xnbFiles.Length == 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// start off the recursive directory printing
|
||||||
|
printDirectoryClass( dir, 2, sourceFolder );
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle any files in the root sourceFolder
|
||||||
|
printContentFiles( sourceFolder, 2, sourceFolder );
|
||||||
|
}
|
||||||
|
|
||||||
|
#>
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<#+
|
||||||
|
// C# reserved keywords
|
||||||
|
private System.Collections.Generic.List<string> keywords = new System.Collections.Generic.List<string>
|
||||||
|
{
|
||||||
|
"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"
|
||||||
|
};
|
||||||
|
|
||||||
|
// recursively creates a class for each directory
|
||||||
|
void printDirectoryClass( string dir, int depth, string sourceFolder )
|
||||||
|
{
|
||||||
|
var dirInfo = new DirectoryInfo( dir );
|
||||||
|
var firstIndent = new string( ' ', depth * 5 );
|
||||||
|
var className = generateClassName( dirInfo.Name, true );
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// handle files
|
||||||
|
printContentFiles( dir, depth + 1, sourceFolder );
|
||||||
|
|
||||||
|
WriteLine( "{0}}}\n", firstIndent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// prints a const string for each file in the directory
|
||||||
|
void printContentFiles( string dir, int depth, string sourceFolder )
|
||||||
|
{
|
||||||
|
var firstIndent = new string( '\t', depth );
|
||||||
|
|
||||||
|
var files = Directory.EnumerateFiles( dir )
|
||||||
|
.Where( s => s.EndsWith( ".xnb" ) || s.EndsWith( ".png" ) || s.EndsWith( ".ogg" ) || s.EndsWith( ".wav" ) || s.EndsWith( ".fxb" ) );
|
||||||
|
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.Replace( ".xnb", string.Empty );
|
||||||
|
var className = generateClassName( fileName, false );
|
||||||
|
|
||||||
|
if( finalPath[0] == '/' || finalPath[0] == '\\' )
|
||||||
|
finalPath = finalPath.Substring( 1 );
|
||||||
|
|
||||||
|
// 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string stripInvalidPathChars( string input )
|
||||||
|
{
|
||||||
|
var invalidChars = Path.GetInvalidPathChars();
|
||||||
|
return new string( input.Where( m => !invalidChars.Contains( m ) ).ToArray<char>() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string stripInvalidFilenameChars( string input )
|
||||||
|
{
|
||||||
|
var invalidChars = Path.GetInvalidFileNameChars();
|
||||||
|
return new string( input.Where( m => !invalidChars.Contains( m ) ).ToArray<char>() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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 );
|
||||||
|
else if( !uppercaseFirstChar && char.IsUpper( className[0] ) )
|
||||||
|
className = char.ToLower( className[0] ) + className.Substring( 1 );
|
||||||
|
|
||||||
|
// 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 );
|
||||||
|
}
|
||||||
|
#>
|
||||||
40
project_name/T4Templates/EnumEqualityComparerGenerator.tt
Normal file
40
project_name/T4Templates/EnumEqualityComparerGenerator.tt
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<#@ template language="C#" hostSpecific="true" #>
|
||||||
|
<#@ assembly name="System.Core" #>
|
||||||
|
<#@ import namespace="System.Collections.Generic" #>
|
||||||
|
<# var enumTypes = new string[] { "System.StringSplitOptions" }; #>
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Nez
|
||||||
|
{
|
||||||
|
<#
|
||||||
|
// loop through all of our enumTypes and generate a comparer
|
||||||
|
foreach( var enumType in enumTypes )
|
||||||
|
{
|
||||||
|
var classPrefix = char.ToUpper( enumType[0] ) + enumType.Substring( 1 ).Replace( ".", string.Empty );
|
||||||
|
if( enumType.IndexOf( "." ) > 0 )
|
||||||
|
{
|
||||||
|
var enumTypeSansNS = enumType.Substring( enumType.IndexOf( "." ) + 1 );
|
||||||
|
classPrefix = char.ToUpper( enumTypeSansNS[0] ) + enumTypeSansNS.Substring( 1 ).Replace( ".", string.Empty );
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteLine( "\tpublic class {0}Comparer : IEqualityComparer<{1}>", classPrefix, enumType );
|
||||||
|
WriteLine( "\t{" );
|
||||||
|
|
||||||
|
WriteLine( "\t\tstatic public readonly {0}Comparer default{0}Comparer = new {0}Comparer();\n", classPrefix );
|
||||||
|
|
||||||
|
WriteLine( "\t\tpublic bool Equals( {0} x, {0} y )", enumType );
|
||||||
|
WriteLine( "\t\t{" );
|
||||||
|
WriteLine( "\t\t\treturn x == y;" );
|
||||||
|
WriteLine( "\t\t}\n\n" );
|
||||||
|
|
||||||
|
WriteLine( "\t\tpublic int GetHashCode( {0} b )", enumType );
|
||||||
|
WriteLine( "\t\t{" );
|
||||||
|
WriteLine( "\t\t\treturn (int)b;" );
|
||||||
|
WriteLine( "\t\t}" );
|
||||||
|
|
||||||
|
WriteLine( "\t}\n\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
#>
|
||||||
|
}
|
||||||
@ -6,13 +6,13 @@
|
|||||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
<AssemblyName>project_name</AssemblyName>
|
<AssemblyName>project_name</AssemblyName>
|
||||||
<MonoGamePlatform>DesktopGL</MonoGamePlatform>
|
<MonoGamePlatform>DesktopGL</MonoGamePlatform>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Reference FNA project -->
|
<!-- Reference FNA project -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="../FNA/FNA.csproj" />
|
<ProjectReference Include="../FNA/FNA.csproj" />
|
||||||
<ProjectReference Include="../Nez.FNA/Nez.FNA/Nez.FNA.csproj" />
|
<ProjectReference Include="../Nez.FNA/Nez.FNA/Nez.FNA.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Include the Content directory (except for .fx files, since we use .fxb at runtime) -->
|
<!-- Include the Content directory (except for .fx files, since we use .fxb at runtime) -->
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user