using Nerfed.Runtime; using System.Reflection; using System.Text.Json; namespace Nerfed.Editor.Project; public class ProjectConfig { public string Name { get; set; } public uint Version { get; set; } public string RuntimeProject { get; set; } } internal static class Project { private const string projectFileName = ".project"; internal static ProjectConfig LoadedConfig { get; private set; } internal static string ProjectDirectory { get; private set; } internal static string ProjectContentDirectory { get; private set; } internal static string ProjectTempDirectory { get; private set; } internal static bool Create(string path, string projectName) { // Check if folder is empty. if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } if(Directory.GetFiles(path).Length != 0) { Log.Error($"Directory {path} is not empty!"); return false; } // Create project file. ProjectConfig projectConfig = new ProjectConfig { Name = projectName, Version = /*Nerfed.Runtime.Verion*/ 1, }; // Create solution. GenerateSolution(path, projectConfig); string projectFilePath = Path.Combine(path, projectFileName); SaveProject(projectFilePath, projectConfig); // Open the project. Open(projectFilePath); Log.Info($"Succesfully created project."); return true; } internal static bool Open(string path) { string projectFilePath = path; if (!File.Exists(projectFilePath)) { projectFilePath = Path.Combine(path, projectFileName); if (!File.Exists(projectFilePath)) { Log.Error($"Project file not found at {path} or {projectFilePath}"); return false; } } // Load from file. string jsonString = File.ReadAllText(projectFilePath); ProjectConfig projectConfig = JsonSerializer.Deserialize(jsonString); // Check version. if(projectConfig.Version != /*Nerfed.Runtime.Verion*/ 1) { Log.Error($"Project runtime version does not match editor runtime verion!"); return false; } LoadedConfig = projectConfig; SetupDefaultFolders(Path.GetDirectoryName(projectFilePath)); Log.Info($"Opened project: {projectConfig.Name}"); return true; } internal static bool SaveProject(string path, ProjectConfig projectConfig) { JsonSerializerOptions options = new JsonSerializerOptions(JsonSerializerOptions.Default) { WriteIndented = true, }; string jsonString = JsonSerializer.Serialize(projectConfig, options); File.WriteAllText(path, jsonString); return true; } // Compile the project using the builder. internal static bool CompileProject() { //GenerateSolution(); //dotnet build return false; } private static void GenerateSolution(string path, ProjectConfig projectConfig) { GenerateCSProjectFiles(path, projectConfig); Log.Info("Generating solution file"); string solution = $@" Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.10.35013.160 MinimumVisualStudioVersion = 10.0.40219.1 Project(""{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}"") = ""{projectConfig.Name}.Runtime"", ""{projectConfig.Name}.Runtime.csproj"", ""{{B04FAEF8-7D91-43A9-81C5-4BD3217B0C23}}"" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Test|x64 = Test|x64 Release|x64 = Release|x64 Debug|x64 = Debug|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {{B04FAEF8-7D91-43A9-81C5-4BD3217B0C23}}.Test|x64.ActiveCfg = Test|x64 {{B04FAEF8-7D91-43A9-81C5-4BD3217B0C23}}.Test|x64.Build.0 = Test|x64 {{B04FAEF8-7D91-43A9-81C5-4BD3217B0C23}}.Release|x64.ActiveCfg = Release|x64 {{B04FAEF8-7D91-43A9-81C5-4BD3217B0C23}}.Release|x64.Build.0 = Release|x64 {{B04FAEF8-7D91-43A9-81C5-4BD3217B0C23}}.Debug|x64.ActiveCfg = Debug|x64 {{B04FAEF8-7D91-43A9-81C5-4BD3217B0C23}}.Debug|x64.Build.0 = Debug|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {{117DD74B-A4DC-48CE-B782-C7AE565A9270}} EndGlobalSection EndGlobal "; string solutionName = projectConfig.Name + ".sln"; string filePath = Path.Combine(path, solutionName); File.WriteAllText(filePath, solution); } // Inspirered by https://github.com/ProwlEngine/Prowl/blob/main/Prowl.Editor/Project.cs // Maybe the builder should do this? // When compiling the 'runtimeAssembly.Location' needs to be updated to where ever the one is that is being used. private static void GenerateCSProjectFiles(string path, ProjectConfig projectConfig) { Log.Info("Generating CS project files"); Assembly[] loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); Assembly runtimeAssembly = loadedAssemblies.FirstOrDefault(assembly => assembly.GetName().Name == "Nerfed.Runtime") ?? throw new Exception("Failed to find Runtime Assembly!"); string propertyGroup = $@" net8.0 enable disable true true true false false Debug;Test;Release x64 TRACE;LOG_INFO;PROFILING TRACE;LOG_ERROR;PROFILING true TRACE;LOG_ERROR true "; string runtimeProject = $@" {propertyGroup} {runtimeAssembly.Location} false "; string runtimeProjectName = projectConfig.Name + ".Runtime.csproj"; string filePath = Path.Combine(path, runtimeProjectName); File.WriteAllText(filePath, runtimeProject); projectConfig.RuntimeProject = runtimeProjectName; Log.Info($"Generated runtime at {filePath}"); // TODO: Editor project. } private static void SetupDefaultFolders(string path) { ProjectDirectory = path; string contentPath = Path.Combine(path, "Content"); if (!Directory.Exists(contentPath)) { Directory.CreateDirectory(contentPath); } ProjectContentDirectory = contentPath; string scriptsPath = Path.Combine(ProjectContentDirectory, "Scripts"); if (!Directory.Exists(scriptsPath)) { Directory.CreateDirectory(scriptsPath); } string scriptsRuntimePath = Path.Combine(scriptsPath, "Runtime"); if (!Directory.Exists(scriptsRuntimePath)) { Directory.CreateDirectory(scriptsRuntimePath); } string tempPath = Path.Combine(path, "Temp"); if (!Directory.Exists(tempPath)) { Directory.CreateDirectory(tempPath); } ProjectTempDirectory = tempPath; } }