diff --git a/Source/Editor/Cooker/Platform/Windows/WindowsPlatformTools.cpp b/Source/Editor/Cooker/Platform/Windows/WindowsPlatformTools.cpp
index 9d3280f4b..5259ca2df 100644
--- a/Source/Editor/Cooker/Platform/Windows/WindowsPlatformTools.cpp
+++ b/Source/Editor/Cooker/Platform/Windows/WindowsPlatformTools.cpp
@@ -511,11 +511,12 @@ bool WindowsPlatformTools::OnDeployBinaries(CookingData& data)
// Rename app
const String newName = EditorUtilities::GetOutputName();
- if (newName != StringUtils::GetFileNameWithoutExtension(files[0]))
+ const StringView oldName = StringUtils::GetFileNameWithoutExtension(files[0]);
+ if (newName != oldName)
{
if (FileSystem::MoveFile(data.NativeCodeOutputPath / newName + TEXT(".exe"), files[0], true))
{
- data.Error(TEXT("Failed to change output executable name."));
+ data.Error(String::Format(TEXT("Failed to change output executable name from '{}' to '{}'."), oldName, newName));
return true;
}
}
diff --git a/Source/Editor/Cooker/Steps/DeployDataStep.cpp b/Source/Editor/Cooker/Steps/DeployDataStep.cpp
index 84a36e5c6..ff22247ef 100644
--- a/Source/Editor/Cooker/Steps/DeployDataStep.cpp
+++ b/Source/Editor/Cooker/Steps/DeployDataStep.cpp
@@ -275,7 +275,7 @@ bool DeployDataStep::Perform(CookingData& data)
DEPLOY_NATIVE_FILE("libmonosgen-2.0.dylib");
DEPLOY_NATIVE_FILE("libSystem.IO.Compression.Native.dylib");
DEPLOY_NATIVE_FILE("libSystem.Native.dylib");
- DEPLOY_NATIVE_FILE("libSystem.NET.Security.Native.dylib");
+ DEPLOY_NATIVE_FILE("libSystem.Net.Security.Native.dylib");
DEPLOY_NATIVE_FILE("libSystem.Security.Cryptography.Native.Apple.dylib");
break;
#undef DEPLOY_NATIVE_FILE
diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
index d2aa85269..e71f9a8bc 100644
--- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
@@ -95,7 +95,21 @@ namespace FlaxEditor.CustomEditors.Dedicated
var cm = new ItemsListContextMenu(180);
for (int i = 0; i < scripts.Count; i++)
{
- cm.AddItem(new TypeSearchPopup.TypeItemView(scripts[i]));
+ var script = scripts[i];
+ var item = new TypeSearchPopup.TypeItemView(script);
+ if (script.GetAttributes(false).FirstOrDefault(x => x is RequireActorAttribute) is RequireActorAttribute requireActor)
+ {
+ var actors = ScriptsEditor.ParentEditor.Values;
+ foreach (var a in actors)
+ {
+ if (a.GetType() != requireActor.RequiredType)
+ {
+ item.Enabled = false;
+ break;
+ }
+ }
+ }
+ cm.AddItem(item);
}
cm.TextChanged += text =>
{
diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs
index d8493a70a..ca053dcab 100644
--- a/Source/Editor/Options/InterfaceOptions.cs
+++ b/Source/Editor/Options/InterfaceOptions.cs
@@ -4,6 +4,7 @@ using System.ComponentModel;
using FlaxEditor.GUI.Docking;
using FlaxEditor.Utilities;
using FlaxEngine;
+using FlaxEngine.GUI;
namespace FlaxEditor.Options
{
@@ -217,6 +218,21 @@ namespace FlaxEditor.Options
[EditorDisplay("Interface"), EditorOrder(320), Tooltip("Toggles tree line visibility in places like the Scene or Content Panel.")]
public bool ShowTreeLines { get; set; } = true;
+ ///
+ /// Gets or sets tooltip text alignment.
+ ///
+ [DefaultValue(TextAlignment.Center)]
+ [EditorDisplay("Interface"), EditorOrder(321)]
+ public TextAlignment TooltipTextAlignment { get => _tooltipTextAlignment;
+ set
+ {
+ _tooltipTextAlignment = value;
+ Style.Current.SharedTooltip.HorizontalTextAlignment = value;
+ }
+ }
+
+ private TextAlignment _tooltipTextAlignment = TextAlignment.Center;
+
///
/// Gets or sets the timestamps prefix mode for output log messages.
///
diff --git a/Source/Editor/Options/OptionsModule.cs b/Source/Editor/Options/OptionsModule.cs
index d43af963e..24dea810e 100644
--- a/Source/Editor/Options/OptionsModule.cs
+++ b/Source/Editor/Options/OptionsModule.cs
@@ -331,6 +331,7 @@ namespace FlaxEditor.Options
SharedTooltip = new Tooltip(),
};
+ style.SharedTooltip.HorizontalTextAlignment = Editor.Instance.Options.Options.Interface.TooltipTextAlignment;
style.DragWindow = style.BackgroundSelected * 0.7f;
return style;
}
@@ -386,6 +387,7 @@ namespace FlaxEditor.Options
SharedTooltip = new Tooltip(),
};
+ style.SharedTooltip.HorizontalTextAlignment = Editor.Instance.Options.Options.Interface.TooltipTextAlignment;
return style;
}
diff --git a/Source/Editor/Utilities/EditorUtilities.cpp b/Source/Editor/Utilities/EditorUtilities.cpp
index 0fc614af5..e3f521437 100644
--- a/Source/Editor/Utilities/EditorUtilities.cpp
+++ b/Source/Editor/Utilities/EditorUtilities.cpp
@@ -5,10 +5,11 @@
#include "Engine/Platform/File.h"
#include "Engine/Platform/FileSystem.h"
#include "Engine/Platform/CreateProcessSettings.h"
-#include "Engine/Core/Log.h"
#include "Engine/Graphics/Textures/TextureData.h"
#include "Engine/Graphics/PixelFormatExtensions.h"
#include "Engine/Tools/TextureTool/TextureTool.h"
+#include "Engine/Core/Log.h"
+#include "Engine/Core/Types/StringBuilder.h"
#include "Engine/Core/Config/GameSettings.h"
#include "Engine/Core/Config/BuildSettings.h"
#include "Engine/Content/Content.h"
@@ -28,6 +29,7 @@ String EditorUtilities::GetOutputName()
outputName.Replace(TEXT("${COMPANY_NAME}"), *gameSettings->CompanyName, StringSearchCase::IgnoreCase);
if (outputName.IsEmpty())
outputName = TEXT("FlaxGame");
+ ValidatePathChars(outputName, 0);
return outputName;
}
@@ -360,6 +362,28 @@ bool EditorUtilities::IsInvalidPathChar(Char c)
return false;
}
+void EditorUtilities::ValidatePathChars(String& filename, char invalidCharReplacement)
+{
+ if (invalidCharReplacement == 0)
+ {
+ StringBuilder result;
+ for (int32 i = 0; i < filename.Length(); i++)
+ {
+ if (!IsInvalidPathChar(filename[i]))
+ result.Append(filename[i]);
+ }
+ filename = result.ToString();
+ }
+ else
+ {
+ for (int32 i = 0; i < filename.Length(); i++)
+ {
+ if (IsInvalidPathChar(filename[i]))
+ filename[i] = invalidCharReplacement;
+ }
+ }
+}
+
bool EditorUtilities::ReplaceInFiles(const String& folderPath, const Char* searchPattern, DirectorySearchOption searchOption, const String& findWhat, const String& replaceWith)
{
Array files;
@@ -391,7 +415,7 @@ bool EditorUtilities::ReplaceInFile(const StringView& file, const Dictionarytrue if the given character cannot be used as a path because it is illegal character; otherwise, false.
static bool IsInvalidPathChar(Char c);
+ ///
+ /// Validates path characters and replaces any incorrect ones.
+ ///
+ /// The input and output filename string to process.
+ /// The character to use for replacement for any invalid characters in the path. Use '0' to remove them.
+ static void ValidatePathChars(String& filename, char invalidCharReplacement = ' ');
+
///
/// Replaces the given text with other one in the files.
///
diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs
index bb7c594b3..6089b2e07 100644
--- a/Source/Editor/Windows/ContentWindow.cs
+++ b/Source/Editor/Windows/ContentWindow.cs
@@ -638,12 +638,14 @@ namespace FlaxEditor.Windows
var toDelete = new List(items);
toDelete.Sort((a, b) => a.IsFolder ? 1 : b.IsFolder ? -1 : a.Compare(b));
+ string singularPlural = toDelete.Count > 1 ? "s" : "";
+
string msg = toDelete.Count == 1
- ? string.Format("Are you sure to delete \'{0}\'?\nThis action cannot be undone. Files will be deleted permanently.", items[0].Path)
- : string.Format("Are you sure to delete {0} selected items?\nThis action cannot be undone. Files will be deleted permanently.", items.Count);
+ ? string.Format("Delete \'{0}\'?\n\nThis action cannot be undone.\nFile will be deleted permanently.", items[0].Path)
+ : string.Format("Delete {0} selected items?\n\nThis action cannot be undone.\nFiles will be deleted permanently.", items.Count);
// Ask user
- if (MessageBox.Show(msg, "Delete asset(s)", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) != DialogResult.OK)
+ if (MessageBox.Show(msg, "Delete asset" + singularPlural, MessageBoxButtons.OKCancel, MessageBoxIcon.Question) != DialogResult.OK)
return;
// Clear navigation
diff --git a/Source/Editor/Windows/GameCookerWindow.cs b/Source/Editor/Windows/GameCookerWindow.cs
index 855faed63..cbe211eca 100644
--- a/Source/Editor/Windows/GameCookerWindow.cs
+++ b/Source/Editor/Windows/GameCookerWindow.cs
@@ -328,6 +328,19 @@ namespace FlaxEditor.Windows
group.Object(new ReadOnlyValueContainer(platformObj));
+ layout.Space(2);
+ var openOutputButton = layout.Button("Open output folder").Button;
+ openOutputButton.TooltipText = "Opens the defined out folder if the path exists.";
+ openOutputButton.Clicked += () =>
+ {
+ string output = StringUtils.ConvertRelativePathToAbsolute(Globals.ProjectFolder, StringUtils.NormalizePath(proxy.PerPlatformOptions[_platform].Output));
+ if (Directory.Exists(output))
+ FlaxEngine.FileSystem.ShowFileExplorer(output);
+ else
+ FlaxEditor.Editor.LogWarning($"Can not open path: {output} because it does not exist.");
+ };
+ layout.Space(2);
+
_buildButton = layout.Button("Build").Button;
_buildButton.Clicked += OnBuildClicked;
}
diff --git a/Source/Engine/Debug/DebugDraw.cpp b/Source/Engine/Debug/DebugDraw.cpp
index 2ae7756da..077bf9b80 100644
--- a/Source/Engine/Debug/DebugDraw.cpp
+++ b/Source/Engine/Debug/DebugDraw.cpp
@@ -2145,4 +2145,8 @@ void DebugDraw::DrawText(const StringView& text, const Transform& transform, con
t.TimeLeft = duration;
}
+void DebugDraw::Clear(void* context)
+{
+ DebugDraw::UpdateContext(context, MAX_float);
+}
#endif
diff --git a/Source/Engine/Debug/DebugDraw.h b/Source/Engine/Debug/DebugDraw.h
index 9c58aa727..bb5cf2e50 100644
--- a/Source/Engine/Debug/DebugDraw.h
+++ b/Source/Engine/Debug/DebugDraw.h
@@ -689,6 +689,12 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// The font size.
/// The duration (in seconds). Use 0 to draw it only once.
API_FUNCTION() static void DrawText(const StringView& text, const Transform& transform, const Color& color = Color::White, int32 size = 32, float duration = 0.0f);
+
+ ///
+ /// Clear all debug draw displayed on sceen.
+ ///
+ ///
+ API_FUNCTION() static void Clear(void* context = nullptr);
};
#define DEBUG_DRAW_AXIS_FROM_DIRECTION(origin, direction, size, duration, depthTest) DebugDraw::DrawAxisFromDirection(origin, direction, size, duration, depthTest);
@@ -721,6 +727,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
#define DEBUG_DRAW_WIRE_ARC(position, orientation, radius, angle, color, duration, depthTest) DebugDraw::DrawWireArc(position, orientation, radius, angle, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_ARROW(position, orientation, scale, capScale, color, duration, depthTest) DebugDraw::DrawWireArrow(position, orientation, scale, capScale, color, duration, depthTest)
#define DEBUG_DRAW_TEXT(text, position, color, size, duration) DebugDraw::DrawText(text, position, color, size, duration)
+#define DEBUG_DRAW_CLEAR(context) DebugDraw::Clear(context)
#else
@@ -753,5 +760,6 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
#define DEBUG_DRAW_WIRE_ARC(position, orientation, radius, angle, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_ARROW(position, orientation, scale, capScale, color, duration, depthTest)
#define DEBUG_DRAW_TEXT(text, position, color, size, duration)
+#define DEBUG_DRAW_CLEAR(context)
#endif
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
index 11157783e..010add151 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
@@ -190,6 +190,11 @@ void WheeledVehicle::SetThrottle(float value)
_throttle = Math::Clamp(value, -1.0f, 1.0f);
}
+float WheeledVehicle::GetThrottle()
+{
+ return _throttle;
+}
+
void WheeledVehicle::SetSteering(float value)
{
_steering = Math::Clamp(value, -1.0f, 1.0f);
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h
index 16e226546..fe518a41d 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.h
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.h
@@ -541,6 +541,12 @@ public:
/// The value (-1,1 range). When using UseReverseAsBrake it can be negative and will be used as brake and backward driving.
API_FUNCTION() void SetThrottle(float value);
+ ///
+ /// Get the vehicle throttle. It is the analog accelerator pedal value in range (0,1) where 1 represents the pedal fully pressed and 0 represents the pedal in its rest state.
+ ///
+ /// The vehicle throttle.
+ API_FUNCTION() float GetThrottle();
+
///
/// Sets the input for vehicle steering. Steer is the analog steer value in range (-1,1) where -1 represents the steering wheel at left lock and +1 represents the steering wheel at right lock.
///
diff --git a/Source/Engine/Tests/TestScripting.h b/Source/Engine/Tests/TestScripting.h
index 19fd76351..dc05750e1 100644
--- a/Source/Engine/Tests/TestScripting.h
+++ b/Source/Engine/Tests/TestScripting.h
@@ -8,6 +8,35 @@
#include "Engine/Scripting/ScriptingObject.h"
#include "Engine/Scripting/SerializableScriptingObject.h"
+// Test default values init on fields.
+API_STRUCT(NoDefault) struct TestDefaultValues
+{
+ DECLARE_SCRIPTING_TYPE_MINIMAL(TestDefaultValues);
+
+ // Default value case 1
+ API_FIELD() float TestFloat1 = {};
+ // Default value case 2
+ API_FIELD() float TestFloat2 = { };
+ // Default value case 3
+ API_FIELD() float TestFloat3 = {1.0f};
+ // Default value case 4
+ API_FIELD() float TestFloat4 = float{};
+ // Default value case 5
+ API_FIELD() float TestFloat5 = float{ };
+ // Default value case 6
+ API_FIELD() float TestFloat6 = float{1.0f};
+ // Default value case 7
+ API_FIELD() float TestFloat7 {};
+ // Default value case 8
+ API_FIELD() float TestFloat8 {1.0f};
+ // Default value case 9
+ API_FIELD() float TestFloat9 = 1.0f;
+ // Default value case 10
+ API_FIELD() float TestFloat10 = 1.f;
+ // Default value case 11
+ API_FIELD() float TestFloat11 = 1;
+};
+
// Test interface (name conflict with namespace)
API_INTERFACE(Namespace="Foo") class FLAXENGINE_API IFoo
{
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp
index 408fcb887..91c2edc06 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp
@@ -1080,11 +1080,7 @@ void TrySetupMaterialParameter(MaterialInstance* instance, Span par
String GetAdditionalImportPath(const String& autoImportOutput, Array& importedFileNames, const String& name)
{
String filename = name;
- for (int32 j = filename.Length() - 1; j >= 0; j--)
- {
- if (EditorUtilities::IsInvalidPathChar(filename[j]))
- filename[j] = ' ';
- }
+ EditorUtilities::ValidatePathChars(filename);
if (importedFileNames.Contains(filename))
{
int32 counter = 1;
diff --git a/Source/Engine/UI/GUI/Tooltip.cs b/Source/Engine/UI/GUI/Tooltip.cs
index a7f80e152..40aae0067 100644
--- a/Source/Engine/UI/GUI/Tooltip.cs
+++ b/Source/Engine/UI/GUI/Tooltip.cs
@@ -17,6 +17,11 @@ namespace FlaxEngine.GUI
private string _currentText;
private Window _window;
+ ///
+ /// The horizontal alignment of the text.
+ ///
+ public TextAlignment HorizontalTextAlignment = TextAlignment.Center;
+
///
/// Gets or sets the time in seconds that mouse have to be over the target to show the tooltip.
///
@@ -236,7 +241,14 @@ namespace FlaxEngine.GUI
// Padding for text
var textRect = GetClientArea();
- textRect.X += 5;
+ float textX = HorizontalTextAlignment switch
+ {
+ TextAlignment.Near => 15,
+ TextAlignment.Center => 5,
+ TextAlignment.Far => -5,
+ _ => throw new ArgumentOutOfRangeException()
+ };
+ textRect.X += textX;
textRect.Width -= 10;
// Tooltip text
@@ -245,7 +257,7 @@ namespace FlaxEngine.GUI
_currentText,
textRect,
style.Foreground,
- TextAlignment.Center,
+ HorizontalTextAlignment,
TextAlignment.Center,
TextWrapping.WrapWords
);
diff --git a/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.dll b/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.dll
index 7ef160291..e64bb6cd7 100644
--- a/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.dll
+++ b/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.dll
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d4bc89abf5a72c9c3dede29d1cbe5ced923d99e99ba82b76c7b25e940e6f4f25
-size 1111552
+oid sha256:a54bca64e921d32525ed58c52ce802b4ca2c3f8a92c342296da48c55ec1ea58d
+size 1112064
diff --git a/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.lib b/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.lib
index 3f70d273b..ae9715a8b 100644
--- a/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.lib
+++ b/Source/Platforms/Windows/Binaries/ThirdParty/x64/OpenAL32.lib
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e7636bd763b099f84d2015fa89635d27d4298b2c8c38ce0335b545ae9e2b4db4
+oid sha256:6a4ac5af61abb19624dc2ae23bc16af09a062655f3eab89fedf6c0ead6cd935a
size 37562
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
index 06d2b9712..9642c8b02 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
@@ -153,6 +153,28 @@ namespace Flax.Build.Bindings
case "false": return value;
}
+ // Handle float{_} style type of default values
+ if (valueType != null && value.StartsWith($"{valueType.Type}") && value.EndsWith("}"))
+ {
+ value = value.Replace($"{valueType.Type}", "").Replace("{", "").Replace("}", "").Trim();
+ if (string.IsNullOrEmpty(value))
+ {
+ value = $"default({valueType.Type})";
+ return value;
+ }
+ }
+
+ // Handle C++ bracket default values that are not arrays
+ if (value.StartsWith("{") && value.EndsWith("}") && valueType != null && !valueType.IsArray && valueType.Type != "Array")
+ {
+ value = value.Replace("{", "").Replace("}", "").Trim();
+ if (string.IsNullOrEmpty(value))
+ {
+ value = $"default({valueType.Type})";
+ return value;
+ }
+ }
+
// Numbers
if (float.TryParse(value, out _) || (value[value.Length - 1] == 'f' && float.TryParse(value.Substring(0, value.Length - 1), out _)))
{
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs
index b2a3604bb..d99fa8b92 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs
@@ -1352,11 +1352,17 @@ namespace Flax.Build.Bindings
desc.Name = ParseName(ref context);
// Read ';' or default value or array size or bit-field size
- token = context.Tokenizer.ExpectAnyTokens(new[] { TokenType.SemiColon, TokenType.Equal, TokenType.LeftBracket, TokenType.Colon });
+ token = context.Tokenizer.ExpectAnyTokens(new[] { TokenType.SemiColon, TokenType.Equal, TokenType.LeftBracket, TokenType.LeftCurlyBrace, TokenType.Colon });
if (token.Type == TokenType.Equal)
{
context.Tokenizer.SkipUntil(TokenType.SemiColon, out desc.DefaultValue, false);
}
+ // Handle ex: API_FIELD() Type FieldName {DefaultValue};
+ else if (token.Type == TokenType.LeftCurlyBrace)
+ {
+ context.Tokenizer.SkipUntil(TokenType.SemiColon, out desc.DefaultValue, false);
+ desc.DefaultValue = '{' + desc.DefaultValue;
+ }
else if (token.Type == TokenType.LeftBracket)
{
// Read the fixed array length
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs b/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs
index b6b5fa83d..f13449192 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs
@@ -77,7 +77,7 @@ namespace Flax.Deps.Dependencies
var buildDir = Path.Combine(root, "build-" + architecture.ToString());
var solutionPath = Path.Combine(buildDir, "OpenAL.sln");
- RunCmake(root, platform, architecture, $"-B\"{buildDir}\" -DBUILD_SHARED_LIBS=OFF");
+ RunCmake(root, platform, architecture, $"-B\"{buildDir}\" -DBUILD_SHARED_LIBS=OFF -DCMAKE_C_FLAGS=\"/D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR /EHsc\" -DCMAKE_CXX_FLAGS=\"/D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR /EHsc\"");
Deploy.VCEnvironment.BuildSolution(solutionPath, configuration, architecture.ToString());
var depsFolder = GetThirdPartyFolder(options, platform, architecture);
foreach (var file in binariesToCopy)
diff --git a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs
index 1830b8efe..88b7a8df5 100644
--- a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs
+++ b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs
@@ -301,7 +301,8 @@ namespace Flax.Build.Projects.VisualStudioCode
json.BeginArray("configurations");
{
var cppProject = solution.Projects.FirstOrDefault(x => x.BaseName == solution.Name || x.Name == solution.Name);
- var csharpProject = solution.Projects.FirstOrDefault(x => x.BaseName == solution.MainProject.Targets[0].Modules[0] || x.Name == solution.MainProject.Targets[0].Modules[0]);
+ var mainProjectModule = solution.MainProject?.Targets.Length != 0 ? solution.MainProject.Targets[0].Modules[0] : null;
+ var csharpProject = mainProjectModule != null ? solution.Projects.FirstOrDefault(x => x.BaseName == mainProjectModule || x.Name == mainProjectModule) : null;
if (cppProject != null)
{