diff --git a/Source/Engine/Core/Log.cpp b/Source/Engine/Core/Log.cpp index 1147c4ff1..e3d97e149 100644 --- a/Source/Engine/Core/Log.cpp +++ b/Source/Engine/Core/Log.cpp @@ -251,19 +251,13 @@ void Log::Logger::Write(LogType type, const StringView& msg) OnError(type, msg); } - // Check if need to show message box with that log message - if (type == LogType::Fatal) - { + // Ensure the error gets written to the disk + if (type == LogType::Fatal || type == LogType::Error) Flush(); - // Process message further - if (type == LogType::Fatal) - Platform::Fatal(msg); - else if (type == LogType::Error) - Platform::Error(msg); - else - Platform::Info(msg); - } + // Check if need to show message box with that log message + if (type == LogType::Fatal) + Platform::Fatal(msg); } const Char* ToString(LogType e) diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.cpp b/Source/Engine/Platform/Windows/WindowsPlatform.cpp index 970ccfa10..c5bc44ab9 100644 --- a/Source/Engine/Platform/Windows/WindowsPlatform.cpp +++ b/Source/Engine/Platform/Windows/WindowsPlatform.cpp @@ -30,6 +30,9 @@ #endif #include "resource.h" +#define CLR_EXCEPTION 0xE0434352 +#define VCPP_EXCEPTION 0xE06D7363 + const Char* WindowsPlatform::ApplicationWindowClass = TEXT("FlaxWindow"); void* WindowsPlatform::Instance = nullptr; @@ -272,6 +275,12 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) LONG CALLBACK SehExceptionHandler(EXCEPTION_POINTERS* ep) { + if (ep->ExceptionRecord->ExceptionCode == CLR_EXCEPTION) + { + // Pass CLR exceptions back to runtime + return EXCEPTION_CONTINUE_SEARCH; + } + // Skip if engine already crashed if (Globals::FatalErrorOccurred) return EXCEPTION_CONTINUE_SEARCH; diff --git a/Source/Engine/Scripting/Scripting.cs b/Source/Engine/Scripting/Scripting.cs index 68da64bf7..3e11b3e14 100644 --- a/Source/Engine/Scripting/Scripting.cs +++ b/Source/Engine/Scripting/Scripting.cs @@ -135,8 +135,13 @@ namespace FlaxEngine { if (e.ExceptionObject is Exception exception) { - Debug.LogError("Unhandled Exception: " + exception.Message); - Debug.LogException(exception); + if (e.IsTerminating && !System.Diagnostics.Debugger.IsAttached) + Platform.Fatal($"Unhandled Exception: {exception}"); + else + { + Debug.LogError($"Unhandled Exception: {exception.Message}"); + Debug.LogException(exception); + } } } diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs index 2d58df0c0..51ce5b647 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs @@ -299,6 +299,8 @@ namespace Flax.Build.Bindings // Object reference property if (typeInfo.IsObjectRef) return GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller); + if (typeInfo.Type == "SoftTypeReference" || typeInfo.Type == "SoftObjectReference") + return typeInfo.Type; // Array or Span or DataContainer #if USE_NETCORE diff --git a/Source/Tools/Flax.Build/Build/Builder.Projects.cs b/Source/Tools/Flax.Build/Build/Builder.Projects.cs index 166e78036..3e403e956 100644 --- a/Source/Tools/Flax.Build/Build/Builder.Projects.cs +++ b/Source/Tools/Flax.Build/Build/Builder.Projects.cs @@ -179,7 +179,7 @@ namespace Flax.Build using (new ProfileEventScope("GenerateProjects")) { // Pick the project format - List projectFormats = new List(); + HashSet projectFormats = new HashSet(); if (Configuration.ProjectFormatVS2022) projectFormats.Add(ProjectFormat.VisualStudio2022); @@ -191,12 +191,17 @@ namespace Flax.Build projectFormats.Add(ProjectFormat.VisualStudio2015); if (Configuration.ProjectFormatVSCode) projectFormats.Add(ProjectFormat.VisualStudioCode); + if (Configuration.ProjectFormatRider) + projectFormats.Add(ProjectFormat.VisualStudio2022); if (!string.IsNullOrEmpty(Configuration.ProjectFormatCustom)) projectFormats.Add(ProjectFormat.Custom); if (projectFormats.Count == 0) projectFormats.Add(Platform.BuildPlatform.DefaultProjectFormat); + // Always generate VS solution files for project (needed for C# Intellisense support) + projectFormats.Add(ProjectFormat.VisualStudio2022); + foreach (ProjectFormat projectFormat in projectFormats) GenerateProject(projectFormat); } @@ -223,6 +228,8 @@ namespace Flax.Build var projectToModulesBuildOptions = new Dictionary>(); Project mainSolutionProject = null; ProjectGenerator nativeProjectGenerator = ProjectGenerator.Create(projectFormat, TargetType.NativeCpp); + var solutionName = rootProject.Name; + var solutionPath = Path.Combine(workspaceRoot, solutionName + '.' + nativeProjectGenerator.SolutionFileExtension); // Group targets by project name and sort groups based on the project (ensures that referenced plugin source projects are generated firstly before main source projects) var targetGroups = new List(); @@ -544,7 +551,7 @@ namespace Flax.Build foreach (var project in projects) { Log.Verbose(project.Name + " -> " + project.Path); - project.Generate(); + project.Generate(solutionPath); } } @@ -623,7 +630,7 @@ namespace Flax.Build using (new ProfileEventScope("GenerateProject")) { Log.Verbose("Project " + rulesProjectName + " -> " + project.Path); - dotNetProjectGenerator.GenerateProject(project); + dotNetProjectGenerator.GenerateProject(project, solutionPath); } projects.Add(project); @@ -636,9 +643,9 @@ namespace Flax.Build using (new ProfileEventScope("CreateSolution")) { solution = nativeProjectGenerator.CreateSolution(); - solution.Name = rootProject.Name; + solution.Name = solutionName; solution.WorkspaceRootPath = workspaceRoot; - solution.Path = Path.Combine(workspaceRoot, solution.Name + '.' + nativeProjectGenerator.SolutionFileExtension); + solution.Path = solutionPath; solution.Projects = projects.ToArray(); solution.MainProject = mainSolutionProject; } diff --git a/Source/Tools/Flax.Build/Configuration.cs b/Source/Tools/Flax.Build/Configuration.cs index 8fa17a235..19522f403 100644 --- a/Source/Tools/Flax.Build/Configuration.cs +++ b/Source/Tools/Flax.Build/Configuration.cs @@ -213,6 +213,12 @@ namespace Flax.Build [CommandLine("vscode", "Generates Visual Studio Code project format files. Valid only with -genproject option.")] public static bool ProjectFormatVSCode = false; + /// + /// Generates Visual Studio 2022 project format files for Rider. Valid only with -genproject option. + /// + [CommandLine("rider", "Generates Visual Studio 2022 project format files for Rider. Valid only with -genproject option.")] + public static bool ProjectFormatRider = false; + /// /// Generates code project files for a custom project format type. Valid only with -genproject option. /// diff --git a/Source/Tools/Flax.Build/Platforms/Linux/LinuxPlatform.cs b/Source/Tools/Flax.Build/Platforms/Linux/LinuxPlatform.cs index 2fabb2c46..44a2c247a 100644 --- a/Source/Tools/Flax.Build/Platforms/Linux/LinuxPlatform.cs +++ b/Source/Tools/Flax.Build/Platforms/Linux/LinuxPlatform.cs @@ -44,7 +44,7 @@ namespace Flax.Build.Platforms Compiler = Configuration.Compiler; else { - for (int ver = 15; ver >= 6; ver--) + for (int ver = 17; ver >= 6; ver--) { var compiler = "clang++-" + ver; if (Which(compiler) != null) diff --git a/Source/Tools/Flax.Build/Platforms/Unix/UnixPlatform.cs b/Source/Tools/Flax.Build/Platforms/Unix/UnixPlatform.cs index 9d9206f0f..b498f66e4 100644 --- a/Source/Tools/Flax.Build/Platforms/Unix/UnixPlatform.cs +++ b/Source/Tools/Flax.Build/Platforms/Unix/UnixPlatform.cs @@ -68,8 +68,11 @@ namespace Flax.Build.Platforms string path = proc.StandardOutput.ReadLine(); Log.Verbose(string.Format("which {0} exit code: {1}, result: {2}", name, proc.ExitCode, path)); - if (proc.ExitCode == 0 && string.IsNullOrEmpty(proc.StandardError.ReadToEnd())) + if (proc.ExitCode == 0) { + string err = proc.StandardError.ReadToEnd(); + if (!string.IsNullOrEmpty(err)) + Log.Verbose(string.Format("which stderr: {0}", err)); return path; } diff --git a/Source/Tools/Flax.Build/Projects/Project.cs b/Source/Tools/Flax.Build/Projects/Project.cs index 148e97485..0c98f73bb 100644 --- a/Source/Tools/Flax.Build/Projects/Project.cs +++ b/Source/Tools/Flax.Build/Projects/Project.cs @@ -253,9 +253,9 @@ namespace Flax.Build.Projects /// /// Generates the project. /// - public virtual void Generate() + public virtual void Generate(string solutionPath) { - Generator.GenerateProject(this); + Generator.GenerateProject(this, solutionPath); } /// diff --git a/Source/Tools/Flax.Build/Projects/ProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/ProjectGenerator.cs index 8641cf81b..a3da268a9 100644 --- a/Source/Tools/Flax.Build/Projects/ProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/ProjectGenerator.cs @@ -52,7 +52,7 @@ namespace Flax.Build.Projects /// Generates the project. /// /// The project. - public abstract void GenerateProject(Project project); + public abstract void GenerateProject(Project project, string solutionPath); /// /// Generates the solution. diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/CSProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/CSProjectGenerator.cs index 266097a3f..4e4e7dbfe 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudio/CSProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudio/CSProjectGenerator.cs @@ -26,7 +26,7 @@ namespace Flax.Build.Projects.VisualStudio public override TargetType? Type => TargetType.DotNet; /// - public override void GenerateProject(Project project) + public override void GenerateProject(Project project, string solutionPath) { var csProjectFileContent = new StringBuilder(); @@ -49,6 +49,11 @@ namespace Flax.Build.Projects.VisualStudio if (vsProject.CSharp.UseFlaxVS && VisualStudioInstance.HasFlaxVS) projectTypes = ProjectTypeGuids.ToOption(ProjectTypeGuids.FlaxVS) + ';' + projectTypes; + // Try to reuse the existing project guid from solution file + vsProject.ProjectGuid = GetProjectGuid(solutionPath, vsProject.Name); + if (vsProject.ProjectGuid == Guid.Empty) + vsProject.ProjectGuid = Guid.NewGuid(); + // Header csProjectFileContent.AppendLine(""); diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/CSSDKProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/CSSDKProjectGenerator.cs index d8aece342..387a0dcff 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudio/CSSDKProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudio/CSSDKProjectGenerator.cs @@ -26,7 +26,7 @@ namespace Flax.Build.Projects.VisualStudio public override TargetType? Type => TargetType.DotNetCore; /// - public override void GenerateProject(Project project) + public override void GenerateProject(Project project, string solutionPath) { var csProjectFileContent = new StringBuilder(); @@ -53,6 +53,11 @@ namespace Flax.Build.Projects.VisualStudio } } + // Try to reuse the existing project guid from solution file + vsProject.ProjectGuid = GetProjectGuid(solutionPath, vsProject.Name); + if (vsProject.ProjectGuid == Guid.Empty) + vsProject.ProjectGuid = Guid.NewGuid(); + // Header csProjectFileContent.AppendLine(""); csProjectFileContent.AppendLine(""); diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/VCProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/VCProjectGenerator.cs index 3e2a6c9b7..84607f6a1 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudio/VCProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudio/VCProjectGenerator.cs @@ -55,7 +55,7 @@ namespace Flax.Build.Projects.VisualStudio } /// - public override void GenerateProject(Project project) + public override void GenerateProject(Project project, string solutionPath) { var vcProjectFileContent = new StringBuilder(); var vcFiltersFileContent = new StringBuilder(); @@ -67,6 +67,13 @@ namespace Flax.Build.Projects.VisualStudio var projectDirectory = Path.GetDirectoryName(project.Path); var filtersDirectory = project.SourceFolderPath; + // Try to reuse the existing project guid from existing files + vsProject.ProjectGuid = GetProjectGuid(vsProject.Path, vsProject.Name); + if (vsProject.ProjectGuid == Guid.Empty) + vsProject.ProjectGuid = GetProjectGuid(solutionPath, vsProject.Name); + if (vsProject.ProjectGuid == Guid.Empty) + vsProject.ProjectGuid = Guid.NewGuid(); + // Header vcProjectFileContent.AppendLine(""); vcProjectFileContent.AppendLine(string.Format("", projectFileToolVersion)); diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProject.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProject.cs index 5ec0ca8e4..b9b2d2383 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProject.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProject.cs @@ -36,20 +36,5 @@ namespace Flax.Build.Projects.VisualStudio } } } - - /// - public override string Path - { - get => base.Path; - set - { - base.Path = value; - - if (ProjectGuid == Guid.Empty) - { - ProjectGuid = VisualStudioProjectGenerator.GetProjectGuid(Path); - } - } - } } } diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProjectGenerator.cs index ecf70f9f8..6dcc12a4f 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProjectGenerator.cs @@ -22,7 +22,7 @@ namespace Flax.Build.Projects.VisualStudio public override Guid ProjectTypeGuid => ProjectTypeGuids.Android; /// - public override void Generate() + public override void Generate(string solutionPath) { var gen = (VisualStudioProjectGenerator)Generator; var projectFileToolVersion = gen.ProjectFileToolVersion; @@ -141,9 +141,10 @@ namespace Flax.Build.Projects.VisualStudio /// /// The path. /// The project ID. - public static Guid GetProjectGuid(string path) + public static Guid GetProjectGuid(string path, string projectName) { - if (File.Exists(path)) + // Look up for the guid in VC++-project file + if (File.Exists(path) && Path.GetExtension(path).Equals(".vcxproj", StringComparison.OrdinalIgnoreCase)) { try { @@ -161,8 +162,25 @@ namespace Flax.Build.Projects.VisualStudio // Hide errors } } + if (File.Exists(path) && Path.GetExtension(path).Equals(".sln", StringComparison.OrdinalIgnoreCase)) + { + try + { + Regex projectRegex = new Regex(@"Project\(.*\) = \""(\S+)\"", \""(\S+)\"", \""{(\S+)}\"""); + MatchCollection matches = projectRegex.Matches(File.ReadAllText(path)); + for (int i = 0; i < matches.Count; i++) + { + if (matches[i].Groups[1].Value == projectName) + return Guid.ParseExact(matches[i].Groups[3].Value, "D"); + } + } + catch + { + // Hide errors + } + } - return Guid.NewGuid(); + return Guid.Empty; } /// @@ -250,7 +268,7 @@ namespace Flax.Build.Projects.VisualStudio } } - // Try to extract info from the existing solution file to make random IDs stable + // Try to extract solution folder info from the existing solution file to make random IDs stable var solutionId = Guid.NewGuid(); var folderIds = new Dictionary(); if (File.Exists(solution.Path)) @@ -266,16 +284,12 @@ namespace Flax.Build.Projects.VisualStudio solutionId = Guid.ParseExact(value.Substring(15), "B"); } - var folderIdsMatch = Regex.Match(contents, "Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"(.*?)\", \"(.*?)\", \"{(.*?)}\""); - if (folderIdsMatch.Success) + var folderIdMatches = new Regex("Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"(.*?)\", \"(.*?)\", \"{(.*?)}\"").Matches(contents); + foreach (Match match in folderIdMatches) { - foreach (Capture capture in folderIdsMatch.Captures) - { - var value = capture.Value.Substring("Project(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"".Length); - var folder = value.Substring(0, value.IndexOf('\"')); - var folderId = Guid.ParseExact(value.Substring(folder.Length * 2 + "\", \"".Length + "\", \"".Length, 38), "B"); - folderIds["Source\\" + folder] = folderId; - } + var folder = match.Groups[1].Value; + var folderId = Guid.ParseExact(match.Groups[3].Value, "D"); + folderIds[folder] = folderId; } } catch (Exception ex) diff --git a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs index eb6c2bb24..fdf1df4e2 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs @@ -38,7 +38,7 @@ namespace Flax.Build.Projects.VisualStudioCode } /// - public override void GenerateProject(Project project) + public override void GenerateProject(Project project, string solutionPath) { // Not used, solution contains all projects definitions } diff --git a/Source/Tools/Flax.Build/Projects/XCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/XCodeProjectGenerator.cs index 48ba9c0f0..85ac0ff7e 100644 --- a/Source/Tools/Flax.Build/Projects/XCodeProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/XCodeProjectGenerator.cs @@ -42,7 +42,7 @@ namespace Flax.Build.Projects } /// - public override void GenerateProject(Project project) + public override void GenerateProject(Project project, string solutionPath) { }