Added builder
Added shader importer
This commit is contained in:
16
Nerfed.Builder/Builder/BuildArgs.cs
Normal file
16
Nerfed.Builder/Builder/BuildArgs.cs
Normal file
@ -0,0 +1,16 @@
|
||||
namespace Nerfed.Builder;
|
||||
|
||||
public class BuildArgs
|
||||
{
|
||||
[Argument("-build")]
|
||||
public bool Build { get; set; }
|
||||
|
||||
[Argument("-projectPath")]
|
||||
public string ProjectPath { get; set; }
|
||||
|
||||
[Argument("-platform")]
|
||||
public string Platform { get; set; }
|
||||
|
||||
[Argument("-content")]
|
||||
public List<string> ContentFiles { get; set; }
|
||||
}
|
119
Nerfed.Builder/Builder/Builder.cs
Normal file
119
Nerfed.Builder/Builder/Builder.cs
Normal file
@ -0,0 +1,119 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Nerfed.Builder;
|
||||
|
||||
public class Builder : IDisposable
|
||||
{
|
||||
private readonly Dictionary<string, IImporter> importers = new Dictionary<string, IImporter>();
|
||||
private readonly RawFileImporter rawFileImporter;
|
||||
|
||||
public Builder()
|
||||
{
|
||||
rawFileImporter = new RawFileImporter();
|
||||
|
||||
ShaderImporter shaderImporter = new ShaderImporter();
|
||||
importers.Add(".vert", shaderImporter); // Vertex shader
|
||||
importers.Add(".frag", shaderImporter); // Fragment shader
|
||||
importers.Add(".tesc", shaderImporter); // Tessellation control shader
|
||||
importers.Add(".tese", shaderImporter); // Tessellation evaluation shader
|
||||
importers.Add(".geom", shaderImporter); // Geometry shader
|
||||
importers.Add(".comp", shaderImporter); // Compute shader
|
||||
}
|
||||
|
||||
public void Run(BuildArgs args)
|
||||
{
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
List<string> contentFiles = args.ContentFiles;
|
||||
string absContentPath = $"{args.ProjectPath}/{PathUtil.ContentFolderName}";
|
||||
|
||||
// If no files are provided, build all content.
|
||||
if (args.ContentFiles == null)
|
||||
{
|
||||
contentFiles = [];
|
||||
CollectAssetFiles(absContentPath, absContentPath, ref contentFiles);
|
||||
}
|
||||
|
||||
string importPath = $"{args.ProjectPath}/{PathUtil.ImportFolderName}";
|
||||
|
||||
ParallelOptions parallelOptions = new ParallelOptions
|
||||
{
|
||||
MaxDegreeOfParallelism = contentFiles.Count
|
||||
};
|
||||
Parallel.ForEach(contentFiles, parallelOptions, relativeFile =>
|
||||
{
|
||||
try
|
||||
{
|
||||
string inFile = $"{args.ProjectPath}/{PathUtil.ContentFolderName}/{relativeFile}";
|
||||
|
||||
if (!File.Exists(inFile))
|
||||
{
|
||||
Console.Error.WriteLine($"Asset file '{relativeFile}' not found");
|
||||
return;
|
||||
}
|
||||
|
||||
string outFile = $"{importPath}/{relativeFile}{PathUtil.ImportedFileExtension}";
|
||||
|
||||
FileInfo inFileInfo = new FileInfo(inFile);
|
||||
FileInfo outFileInfo = new FileInfo(outFile);
|
||||
|
||||
if (!FileUtil.IsNewer(inFileInfo, outFileInfo))
|
||||
{
|
||||
// File has not changed since last build, no need to build this one.
|
||||
return;
|
||||
}
|
||||
|
||||
string outDir = Path.GetDirectoryName(outFile);
|
||||
if (!Directory.Exists(outDir))
|
||||
{
|
||||
Directory.CreateDirectory(outDir);
|
||||
}
|
||||
|
||||
string ext = Path.GetExtension(inFile).ToLower();
|
||||
if (importers.TryGetValue(ext, out IImporter importer))
|
||||
{
|
||||
importer.Import(inFile, outFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
rawFileImporter.Import(inFile, outFile);
|
||||
}
|
||||
|
||||
Console.WriteLine(relativeFile);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.Error.WriteLine($"Import error on asset '{relativeFile}': {e.Message}");
|
||||
}
|
||||
});
|
||||
|
||||
Console.WriteLine($"Build content completed in {stopwatch.Elapsed.TotalSeconds:F2} seconds");
|
||||
}
|
||||
|
||||
private void CollectAssetFiles(string assetDir, string dir, ref List<string> files)
|
||||
{
|
||||
foreach (string file in Directory.EnumerateFiles(dir))
|
||||
{
|
||||
if (Path.GetExtension(file).Equals(PathUtil.ImportFileExtension, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string relativeFile = file.Substring(assetDir.Length, file.Length - assetDir.Length);
|
||||
if (relativeFile[0] == Path.DirectorySeparatorChar || relativeFile[0] == Path.AltDirectorySeparatorChar)
|
||||
{
|
||||
relativeFile = relativeFile.Substring(1, relativeFile.Length - 1);
|
||||
}
|
||||
|
||||
files.Add(relativeFile);
|
||||
}
|
||||
|
||||
foreach (string subDir in Directory.EnumerateDirectories(dir))
|
||||
{
|
||||
CollectAssetFiles(assetDir, subDir, ref files);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
}
|
39
Nerfed.Builder/Builder/FileUtil.cs
Normal file
39
Nerfed.Builder/Builder/FileUtil.cs
Normal file
@ -0,0 +1,39 @@
|
||||
namespace Nerfed.Builder;
|
||||
|
||||
public static class FileUtil
|
||||
{
|
||||
public static void Copy(string srcFile, string dstFile) {
|
||||
string dstDir = Path.GetDirectoryName(dstFile);
|
||||
if(!Directory.Exists(dstDir)) {
|
||||
Directory.CreateDirectory(dstDir);
|
||||
}
|
||||
|
||||
File.Copy(srcFile, dstFile, true);
|
||||
UpdateFileTimeAttributes(dstFile);
|
||||
}
|
||||
|
||||
public static void WriteBytes(string dstFile, byte[] bytes) {
|
||||
File.WriteAllBytes(dstFile, bytes);
|
||||
UpdateFileTimeAttributes(dstFile);
|
||||
}
|
||||
|
||||
public static void UpdateFileTimeAttributes(string file) {
|
||||
// Copy over date time attributes so we can check if the file changed.
|
||||
FileInfo dstFileInfo = new FileInfo(file);
|
||||
DateTime now = DateTime.Now;
|
||||
DateTime utcNow = DateTime.UtcNow;
|
||||
dstFileInfo.CreationTime = now;
|
||||
dstFileInfo.CreationTimeUtc = utcNow;
|
||||
dstFileInfo.LastWriteTime = now;
|
||||
dstFileInfo.LastWriteTimeUtc = utcNow;
|
||||
dstFileInfo.LastAccessTime = now;
|
||||
dstFileInfo.LastAccessTimeUtc = utcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if the inFileInfo is newer than the outFileInfo.
|
||||
/// </summary>
|
||||
public static bool IsNewer(FileInfo inFileInfo, FileInfo outFileInfo) {
|
||||
return !outFileInfo.Exists || outFileInfo.LastWriteTime <= inFileInfo.LastWriteTime;
|
||||
}
|
||||
}
|
6
Nerfed.Builder/Builder/IImporter.cs
Normal file
6
Nerfed.Builder/Builder/IImporter.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Nerfed.Builder;
|
||||
|
||||
public interface IImporter
|
||||
{
|
||||
void Import(string inFile, string outFile);
|
||||
}
|
9
Nerfed.Builder/Builder/Importers/RawFileImporter.cs
Normal file
9
Nerfed.Builder/Builder/Importers/RawFileImporter.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Nerfed.Builder;
|
||||
|
||||
public class RawFileImporter : IImporter
|
||||
{
|
||||
public void Import(string inFile, string outFile)
|
||||
{
|
||||
FileUtil.Copy(inFile, outFile);
|
||||
}
|
||||
}
|
33
Nerfed.Builder/Builder/Importers/ShaderImporter.cs
Normal file
33
Nerfed.Builder/Builder/Importers/ShaderImporter.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Nerfed.Builder;
|
||||
|
||||
public class ShaderImporter : IImporter
|
||||
{
|
||||
public void Import(string inFile, string outFile)
|
||||
{
|
||||
using (Process proc = new Process())
|
||||
{
|
||||
string glslc;
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
glslc = "Win64/glslc.exe";
|
||||
}
|
||||
else if (OperatingSystem.IsLinux())
|
||||
{
|
||||
glslc = "Linux/glslc";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PlatformNotSupportedException("No shader compiler found for current platform");
|
||||
}
|
||||
|
||||
proc.StartInfo.FileName = glslc;
|
||||
proc.StartInfo.Arguments = @$"""{inFile}"" -o ""{outFile}"" -c";
|
||||
proc.StartInfo.CreateNoWindow = true;
|
||||
proc.StartInfo.UseShellExecute = false;
|
||||
proc.Start();
|
||||
proc.WaitForExit();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user