diff --git a/Source/Editor/Scripting/CodeEditor.cpp b/Source/Editor/Scripting/CodeEditor.cpp
index 198d28396..1cfc4e737 100644
--- a/Source/Editor/Scripting/CodeEditor.cpp
+++ b/Source/Editor/Scripting/CodeEditor.cpp
@@ -180,7 +180,22 @@ void CodeEditingManager::OpenSolution(CodeEditorTypes editorType)
const auto editor = GetCodeEditor(editorType);
if (editor)
{
- OpenSolution(editor);
+ // Ensure that no async task is running
+ if (IsAsyncOpenRunning())
+ {
+ // TODO: enqueue action and handle many actions in the queue
+ LOG(Warning, "Cannot use code editor during async open action.");
+ return;
+ }
+
+ if (editor->UseAsyncForOpen())
+ {
+ AsyncOpenTask::OpenSolution(editor);
+ }
+ else
+ {
+ editor->OpenSolution();
+ }
}
else
{
@@ -201,26 +216,6 @@ void CodeEditingManager::OnFileAdded(CodeEditorTypes editorType, const String& p
}
}
-void CodeEditingManager::OpenSolution(CodeEditor* editor)
-{
- // Ensure that no async task is running
- if (IsAsyncOpenRunning())
- {
- // TODO: enqueue action and handle many actions in the queue
- LOG(Warning, "Cannot use code editor during async open action.");
- return;
- }
-
- if (editor->UseAsyncForOpen())
- {
- AsyncOpenTask::OpenSolution(editor);
- }
- else
- {
- editor->OpenSolution();
- }
-}
-
void OnAsyncBegin(Thread* thread)
{
ASSERT(AsyncOpenThread == nullptr);
diff --git a/Source/Editor/Scripting/CodeEditor.h b/Source/Editor/Scripting/CodeEditor.h
index 638f1d997..a837f0d6e 100644
--- a/Source/Editor/Scripting/CodeEditor.h
+++ b/Source/Editor/Scripting/CodeEditor.h
@@ -193,12 +193,6 @@ public:
/// The path.
API_FUNCTION() static void OnFileAdded(CodeEditorTypes editorType, const String& path);
- ///
- /// Opens the solution project. Handles async opening.
- ///
- /// The code editor.
- static void OpenSolution(CodeEditor* editor);
-
///
/// The asynchronous open begins.
///
diff --git a/Source/Editor/Scripting/ScriptsBuilder.cpp b/Source/Editor/Scripting/ScriptsBuilder.cpp
index 8005524e7..25e22eaca 100644
--- a/Source/Editor/Scripting/ScriptsBuilder.cpp
+++ b/Source/Editor/Scripting/ScriptsBuilder.cpp
@@ -156,7 +156,7 @@ bool ScriptsBuilder::IsSourceWorkspaceDirty()
return _wasProjectStructureChanged;
}
-bool ScriptsBuilder::IsSourceDirty(const TimeSpan& timeout)
+bool ScriptsBuilder::IsSourceDirtyFor(const TimeSpan& timeout)
{
ScopeLock scopeLock(_locker);
return _lastSourceCodeEdited > (_lastCompileAction + timeout);
@@ -626,7 +626,7 @@ void ScriptsBuilderService::Update()
// Check if compile code (if has been edited)
const TimeSpan timeToCallCompileIfDirty = TimeSpan::FromMilliseconds(50);
auto mainWindow = Engine::MainWindow;
- if (ScriptsBuilder::IsSourceDirty(timeToCallCompileIfDirty) && mainWindow && mainWindow->IsFocused())
+ if (ScriptsBuilder::IsSourceDirtyFor(timeToCallCompileIfDirty) && mainWindow && mainWindow->IsFocused())
{
// Check if auto reload is enabled
if (Editor::Managed->CanAutoReloadScripts())
diff --git a/Source/Editor/Scripting/ScriptsBuilder.h b/Source/Editor/Scripting/ScriptsBuilder.h
index df6ff604a..52fdd8457 100644
--- a/Source/Editor/Scripting/ScriptsBuilder.h
+++ b/Source/Editor/Scripting/ScriptsBuilder.h
@@ -63,7 +63,7 @@ public:
///
/// Time to use for checking.
/// True if source code is dirty, otherwise false.
- static bool IsSourceDirty(const TimeSpan& timeout);
+ static bool IsSourceDirtyFor(const TimeSpan& timeout);
///
/// Returns true if scripts are being now compiled/reloaded.
diff --git a/Source/Engine/Graphics/PixelFormatExtensions.cpp b/Source/Engine/Graphics/PixelFormatExtensions.cpp
index e79699830..c22c9aba6 100644
--- a/Source/Engine/Graphics/PixelFormatExtensions.cpp
+++ b/Source/Engine/Graphics/PixelFormatExtensions.cpp
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
#include "PixelFormatExtensions.h"
-#include "Engine/Core/Collections/Dictionary.h"
#include "Engine/Core/Math/Math.h"
// ReSharper disable CppClangTidyClangDiagnosticSwitchEnum
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
index 5c419ccb5..e7e4b5133 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
@@ -19,6 +19,7 @@ namespace Flax.Build.Bindings
internal static readonly Dictionary CSharpNativeToManagedBasicTypes = new Dictionary()
{
// Language types
+ { "bool", "bool" },
{ "int8", "sbyte" },
{ "int16", "short" },
{ "int32", "int" },
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs
index 0072c1240..e9d2076ed 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs
@@ -19,7 +19,7 @@ namespace Flax.Build.Bindings
partial class BindingsGenerator
{
private static readonly Dictionary TypeCache = new Dictionary();
- private const int CacheVersion = 11;
+ private const int CacheVersion = 12;
internal static void Write(BinaryWriter writer, string e)
{
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs
index 77821e29f..25269ca6a 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs
@@ -16,6 +16,7 @@ namespace Flax.Build.Bindings
private static readonly string[] CppParamsThatNeedConversionWrappers = new string[64];
private static readonly string[] CppParamsThatNeedConversionTypes = new string[64];
private static readonly string[] CppParamsWrappersCache = new string[64];
+ public static readonly List> CppInternalCalls = new List>();
public static readonly List CppUsedNonPodTypes = new List();
private static readonly List CppUsedNonPodTypesList = new List();
public static readonly HashSet CppReferencesFiles = new HashSet();
@@ -771,8 +772,53 @@ namespace Flax.Build.Bindings
return $"MUtils::Box<{nativeType}>({value}, {GenerateCppGetNativeClass(buildData, typeInfo, caller, null)})";
}
+ private static bool GenerateCppWrapperFunctionImplicitBinding(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller)
+ {
+ if (typeInfo.IsVoid)
+ return true;
+ if (typeInfo.IsPtr || typeInfo.IsRef || typeInfo.IsArray || typeInfo.IsBitField || (typeInfo.GenericArgs != null && typeInfo.GenericArgs.Count != 0))
+ return false;
+ if (CSharpNativeToManagedBasicTypes.ContainsKey(typeInfo.Type) || CSharpNativeToManagedBasicTypes.ContainsValue(typeInfo.Type))
+ return true;
+ var apiType = FindApiTypeInfo(buildData, typeInfo, caller);
+ if (apiType != null)
+ {
+ if (apiType.IsEnum)
+ return true;
+ }
+ return false;
+ }
+
+ private static bool GenerateCppWrapperFunctionImplicitBinding(BuildData buildData, FunctionInfo functionInfo, ApiTypeInfo caller)
+ {
+ if (!functionInfo.IsStatic || functionInfo.Access != AccessLevel.Public || (functionInfo.Glue.CustomParameters != null && functionInfo.Glue.CustomParameters.Count != 0))
+ return false;
+ if (!GenerateCppWrapperFunctionImplicitBinding(buildData, functionInfo.ReturnType, caller))
+ return false;
+ for (int i = 0; i < functionInfo.Parameters.Count; i++)
+ {
+ var parameterInfo = functionInfo.Parameters[i];
+ if (parameterInfo.IsOut || parameterInfo.IsRef || !GenerateCppWrapperFunctionImplicitBinding(buildData, parameterInfo.Type, caller))
+ return false;
+ }
+ return true;
+ }
+
private static void GenerateCppWrapperFunction(BuildData buildData, StringBuilder contents, ApiTypeInfo caller, FunctionInfo functionInfo, string callFormat = "{0}({1})")
{
+ // Optimize static function wrappers that match C# internal call ABI exactly
+ // Use it for Engine-internally only because in games this makes it problematic to use the same function name but with different signature that is not visible to scripting
+ if (CurrentModule.Module is EngineModule && callFormat == "{0}({1})" && GenerateCppWrapperFunctionImplicitBinding(buildData, functionInfo, caller))
+ {
+ // Ensure the function name is unique within a class/structure
+ if (caller is ClassStructInfo classStructInfo && classStructInfo.Functions.All(f => f.Name != functionInfo.Name || f == functionInfo))
+ {
+ // Use native method binding directly (no generated wrapper)
+ CppInternalCalls.Add(new KeyValuePair(functionInfo.UniqueName, classStructInfo.Name + "::" + functionInfo.Name));
+ return;
+ }
+ }
+
// Setup function binding glue to ensure that wrapper method signature matches for C++ and C#
functionInfo.Glue = new FunctionInfo.GlueInfo
{
@@ -797,6 +843,7 @@ namespace Flax.Build.Bindings
});
}
+ CppInternalCalls.Add(new KeyValuePair(functionInfo.UniqueName, functionInfo.UniqueName));
contents.AppendFormat(" static {0} {1}(", returnValueType, functionInfo.UniqueName);
var separator = false;
@@ -1453,6 +1500,7 @@ namespace Flax.Build.Bindings
var useScripting = classInfo.IsStatic || classInfo.IsScriptingObject;
var useCSharp = EngineConfiguration.WithCSharp(buildData.TargetOptions);
var hasInterface = classInfo.Interfaces != null && classInfo.Interfaces.Any(x => x.Access == AccessLevel.Public);
+ CppInternalCalls.Clear();
if (classInfo.IsAutoSerialization)
GenerateCppAutoSerialization(buildData, contents, moduleInfo, classInfo, classTypeNameNative);
@@ -1520,7 +1568,7 @@ namespace Flax.Build.Bindings
{
// Convert value back from managed to native (could be modified there)
paramType.IsRef = false;
- var managedToNative = GenerateCppWrapperManagedToNative(buildData, paramType, classInfo, out var managedType, null, out var _);
+ var managedToNative = GenerateCppWrapperManagedToNative(buildData, paramType, classInfo, out var managedType, null, out _);
var passAsParamPtr = managedType.EndsWith("*");
var paramValue = $"({managedType}{(passAsParamPtr ? "" : "*")})params[{i}]";
if (!string.IsNullOrEmpty(managedToNative))
@@ -1538,6 +1586,7 @@ namespace Flax.Build.Bindings
contents.Append(" }").AppendLine().AppendLine();
// C# event wrapper binding method (binds/unbinds C# wrapper to C++ delegate)
+ CppInternalCalls.Add(new KeyValuePair(eventInfo.Name + "_Bind", eventInfo.Name + "_ManagedBind"));
contents.AppendFormat(" static void {0}_ManagedBind(", eventInfo.Name);
if (!eventInfo.IsStatic)
contents.AppendFormat("{0}* obj, ", classTypeNameNative);
@@ -1685,47 +1734,9 @@ namespace Flax.Build.Bindings
}
if (useScripting && useCSharp)
{
- foreach (var eventInfo in classInfo.Events)
+ foreach (var e in CppInternalCalls)
{
- if (eventInfo.IsHidden)
- continue;
- contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{eventInfo.Name}_Bind\", &{eventInfo.Name}_ManagedBind);");
- }
- foreach (var fieldInfo in classInfo.Fields)
- {
- if (fieldInfo.IsHidden)
- continue;
- if (fieldInfo.Getter != null)
- contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{fieldInfo.Getter.UniqueName}\", &{fieldInfo.Getter.UniqueName});");
- if (fieldInfo.Setter != null)
- contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{fieldInfo.Setter.UniqueName}\", &{fieldInfo.Setter.UniqueName});");
- }
- foreach (var propertyInfo in classInfo.Properties)
- {
- if (propertyInfo.IsHidden)
- continue;
- if (propertyInfo.Getter != null)
- contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{propertyInfo.Getter.UniqueName}\", &{propertyInfo.Getter.UniqueName});");
- if (propertyInfo.Setter != null)
- contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{propertyInfo.Setter.UniqueName}\", &{propertyInfo.Setter.UniqueName});");
- }
- foreach (var functionInfo in classInfo.Functions)
- {
- if (functionInfo.IsHidden)
- continue;
- contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{functionInfo.UniqueName}\", &{functionInfo.UniqueName});");
- }
- if (hasInterface)
- {
- foreach (var interfaceInfo in classInfo.Interfaces)
- {
- if (interfaceInfo.Access != AccessLevel.Public)
- continue;
- foreach (var functionInfo in interfaceInfo.Functions)
- {
- contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{functionInfo.UniqueName}\", &{functionInfo.UniqueName});");
- }
- }
+ contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{e.Key}\", &{e.Value});");
}
}
GenerateCppClassInitRuntime?.Invoke(buildData, classInfo, contents);
@@ -1801,6 +1812,7 @@ namespace Flax.Build.Bindings
if (structureInfo.Parent != null && !(structureInfo.Parent is FileInfo))
structureTypeNameInternal = structureInfo.Parent.FullNameNative + '_' + structureTypeNameInternal;
var useCSharp = EngineConfiguration.WithCSharp(buildData.TargetOptions);
+ CppInternalCalls.Clear();
if (structureInfo.IsAutoSerialization)
GenerateCppAutoSerialization(buildData, contents, moduleInfo, structureInfo, structureTypeNameNative);
@@ -1869,12 +1881,9 @@ namespace Flax.Build.Bindings
if (useCSharp)
{
- foreach (var fieldInfo in structureInfo.Fields)
+ foreach (var e in CppInternalCalls)
{
- if (fieldInfo.Getter != null)
- contents.AppendLine($" ADD_INTERNAL_CALL(\"{structureTypeNameManagedInternalCall}::Internal_{fieldInfo.Getter.UniqueName}\", &{fieldInfo.Getter.UniqueName});");
- if (fieldInfo.Setter != null)
- contents.AppendLine($" ADD_INTERNAL_CALL(\"{structureTypeNameManagedInternalCall}::Internal_{fieldInfo.Setter.UniqueName}\", &{fieldInfo.Setter.UniqueName});");
+ contents.AppendLine($" ADD_INTERNAL_CALL(\"{structureTypeNameManagedInternalCall}::Internal_{e.Key}\", &{e.Value});");
}
}
@@ -2189,6 +2198,7 @@ namespace Flax.Build.Bindings
CppIncludeFilesList.Clear();
CppVariantToTypes.Clear();
CppVariantFromTypes.Clear();
+ CurrentModule = moduleInfo;
// Disable C# scripting based on configuration
ScriptingLangInfos[0].Enabled = EngineConfiguration.WithCSharp(buildData.TargetOptions);
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs
index 7a84947b0..ca683066a 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs
@@ -48,6 +48,7 @@ namespace Flax.Build.Bindings
public static event GenerateModuleBindingsDelegate GenerateModuleBindings;
public static event GenerateBinaryModuleBindingsDelegate GenerateBinaryModuleBindings;
+ public static ModuleInfo CurrentModule;
public static ModuleInfo ParseModule(BuildData buildData, Module module, BuildOptions moduleOptions = null)
{
diff --git a/Source/Tools/Flax.Build/Bindings/ClassStructInfo.cs b/Source/Tools/Flax.Build/Bindings/ClassStructInfo.cs
index 36d97cfde..3f212a3a5 100644
--- a/Source/Tools/Flax.Build/Bindings/ClassStructInfo.cs
+++ b/Source/Tools/Flax.Build/Bindings/ClassStructInfo.cs
@@ -16,6 +16,7 @@ namespace Flax.Build.Bindings
public ClassStructInfo BaseType;
public List Interfaces;
public List Inheritance; // Data from parsing, used to interfaces and base type construct in Init
+ public List Functions = new List();
public override void Init(Builder.BuildData buildData)
{
@@ -52,6 +53,7 @@ namespace Flax.Build.Bindings
writer.Write((byte)BaseTypeInheritance);
BindingsGenerator.Write(writer, BaseType);
BindingsGenerator.Write(writer, Inheritance);
+ BindingsGenerator.Write(writer, Functions);
base.Write(writer);
}
@@ -62,6 +64,7 @@ namespace Flax.Build.Bindings
BaseTypeInheritance = (AccessLevel)reader.ReadByte();
BaseType = BindingsGenerator.Read(reader, BaseType);
Inheritance = BindingsGenerator.Read(reader, Inheritance);
+ Functions = BindingsGenerator.Read(reader, Functions);
base.Read(reader);
}
@@ -72,8 +75,6 @@ namespace Flax.Build.Bindings
///
public abstract class VirtualClassInfo : ClassStructInfo
{
- public List Functions = new List();
-
internal HashSet UniqueFunctionNames;
public override void Init(Builder.BuildData buildData)
@@ -100,20 +101,6 @@ namespace Flax.Build.Bindings
public abstract int GetScriptVTableOffset(VirtualClassInfo classInfo);
- public override void Write(BinaryWriter writer)
- {
- BindingsGenerator.Write(writer, Functions);
-
- base.Write(writer);
- }
-
- public override void Read(BinaryReader reader)
- {
- Functions = BindingsGenerator.Read(reader, Functions);
-
- base.Read(reader);
- }
-
public override void AddChild(ApiTypeInfo apiTypeInfo)
{
apiTypeInfo.Namespace = null;
diff --git a/Source/Tools/Flax.Build/Bindings/StructureInfo.cs b/Source/Tools/Flax.Build/Bindings/StructureInfo.cs
index adc527c18..24c700c22 100644
--- a/Source/Tools/Flax.Build/Bindings/StructureInfo.cs
+++ b/Source/Tools/Flax.Build/Bindings/StructureInfo.cs
@@ -12,7 +12,6 @@ namespace Flax.Build.Bindings
public class StructureInfo : ClassStructInfo
{
public List Fields = new List();
- public List Functions = new List();
public bool IsAutoSerialization;
public bool ForceNoPod;