diff --git a/Source/Engine/Physics/D6Joint.cs b/Source/Engine/Physics/D6Joint.cs
index c3125a470..5044ad54a 100644
--- a/Source/Engine/Physics/D6Joint.cs
+++ b/Source/Engine/Physics/D6Joint.cs
@@ -6,11 +6,6 @@ namespace FlaxEngine
{
partial struct D6JointDrive
{
- ///
- /// The default structure.
- ///
- public static readonly D6JointDrive Default = new D6JointDrive(0.0f, 0.0f, float.MaxValue, false);
-
///
/// Initializes a new instance of the struct.
///
diff --git a/Source/Engine/Physics/HingeJoint.cs b/Source/Engine/Physics/HingeJoint.cs
index ddb0ed855..8b6155b63 100644
--- a/Source/Engine/Physics/HingeJoint.cs
+++ b/Source/Engine/Physics/HingeJoint.cs
@@ -4,11 +4,6 @@ namespace FlaxEngine
{
partial struct HingeJointDrive
{
- ///
- /// The default structure.
- ///
- public static readonly HingeJointDrive Default = new HingeJointDrive(0.0f, float.MaxValue, 1.0f, false);
-
///
/// Initializes a new instance of the struct.
///
diff --git a/Source/Engine/Physics/Limits.cs b/Source/Engine/Physics/Limits.cs
index f067e7e77..a02a2888c 100644
--- a/Source/Engine/Physics/Limits.cs
+++ b/Source/Engine/Physics/Limits.cs
@@ -4,11 +4,6 @@ namespace FlaxEngine
{
partial struct SpringParameters
{
- ///
- /// The default structure.
- ///
- public static readonly SpringParameters Default = new SpringParameters(0.0f, 0.0f);
-
///
/// Constructs a spring.
///
@@ -23,11 +18,6 @@ namespace FlaxEngine
partial struct LimitLinearRange
{
- ///
- /// The default structure with empty limit.
- ///
- public static readonly LimitLinearRange Default = new LimitLinearRange(0.0f, 0.0f);
-
///
/// Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop.
///
@@ -62,11 +52,6 @@ namespace FlaxEngine
partial struct LimitLinear
{
- ///
- /// The default structure with empty limit.
- ///
- public static readonly LimitLinear Default = new LimitLinear(0.0f);
-
///
/// Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop.
///
@@ -97,11 +82,6 @@ namespace FlaxEngine
partial struct LimitAngularRange
{
- ///
- /// The default structure with empty limit.
- ///
- public static readonly LimitAngularRange Default = new LimitAngularRange(0.0f, 0.0f);
-
///
/// Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop.
///
@@ -136,11 +116,6 @@ namespace FlaxEngine
partial struct LimitConeRange
{
- ///
- /// The default structure with a 45 degree cone limit.
- ///
- public static readonly LimitConeRange Default = new LimitConeRange(90.0f, 90.0f);
-
///
/// Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop.
///
diff --git a/Source/Engine/Platform/CreateWindowSettings.h b/Source/Engine/Platform/CreateWindowSettings.h
index 461f07458..d756b26d2 100644
--- a/Source/Engine/Platform/CreateWindowSettings.h
+++ b/Source/Engine/Platform/CreateWindowSettings.h
@@ -29,7 +29,7 @@ API_ENUM() enum class WindowStartPosition
///
/// Settings for new window.
///
-API_STRUCT() struct CreateWindowSettings
+API_STRUCT(NoDefault) struct CreateWindowSettings
{
DECLARE_SCRIPTING_TYPE_MINIMAL(CreateWindowSettings);
diff --git a/Source/Engine/Platform/SettingsBase.cs b/Source/Engine/Platform/SettingsBase.cs
index 84f02129d..505195819 100644
--- a/Source/Engine/Platform/SettingsBase.cs
+++ b/Source/Engine/Platform/SettingsBase.cs
@@ -16,33 +16,8 @@ namespace FlaxEditor.Content.Settings
///
public GraphicsSettings()
{
- // Initialize PostFx settings with default options (C# structs doesn't support it)
+ // Initialize PostFx settings with default options (C# structs don't support it)
PostProcessSettings = FlaxEngine.PostProcessSettings.Default;
}
}
}
-
-namespace FlaxEngine
-{
- partial struct PostProcessSettings
- {
- private static PostProcessSettings _default;
-
- ///
- /// The default .
- ///
- public static PostProcessSettings Default
- {
- get
- {
- if (!_default.AmbientOcclusion.Enabled)
- {
- object obj = _default;
- Utils.InitStructure(obj, typeof(PostProcessSettings));
- _default = (PostProcessSettings)obj;
- }
- return _default;
- }
- }
- }
-}
diff --git a/Source/Engine/Render2D/TextLayoutOptions.h b/Source/Engine/Render2D/TextLayoutOptions.h
index c41e1306e..cccd146d7 100644
--- a/Source/Engine/Render2D/TextLayoutOptions.h
+++ b/Source/Engine/Render2D/TextLayoutOptions.h
@@ -49,7 +49,7 @@ API_ENUM() enum class TextWrapping
///
/// Structure which describes text layout properties.
///
-API_STRUCT() struct TextLayoutOptions
+API_STRUCT(NoDefault) struct TextLayoutOptions
{
DECLARE_SCRIPTING_TYPE_MINIMAL(TextLayoutOptions);
diff --git a/Source/Engine/Utilities/Utils.cs b/Source/Engine/Utilities/Utils.cs
index a2eb05c58..b5213e2c3 100644
--- a/Source/Engine/Utilities/Utils.cs
+++ b/Source/Engine/Utilities/Utils.cs
@@ -928,7 +928,12 @@ namespace FlaxEngine
stream.Write(0);
}
- internal static void InitStructure(object obj, Type type)
+ ///
+ /// Initializes the structure (value type) by inflating it with values from (recursive).
+ ///
+ /// The object to initialize.
+ /// The structure type.
+ public static void InitStructure(object obj, Type type)
{
var fields = type.GetFields(BindingFlags.Default | BindingFlags.Instance | BindingFlags.Public);
for (var i = 0; i < fields.Length; i++)
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
index b8fa0b254..eaafcc615 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
@@ -1148,6 +1148,7 @@ namespace Flax.Build.Bindings
indent += " ";
// Fields
+ var hasDefaultMember = false;
foreach (var fieldInfo in structureInfo.Fields)
{
contents.AppendLine();
@@ -1164,6 +1165,7 @@ namespace Flax.Build.Bindings
contents.Append("const ");
else if (fieldInfo.IsStatic)
contents.Append("static ");
+ hasDefaultMember |= string.Equals(fieldInfo.Name, "Default", StringComparison.Ordinal);
string type;
if (fieldInfo.Type.IsArray && (fieldInfo.NoArray || structureInfo.IsPod))
@@ -1234,6 +1236,45 @@ namespace Flax.Build.Bindings
}
}
+ // Default value
+ if (!structureInfo.NoDefault && !hasDefaultMember)
+ {
+ contents.AppendLine();
+ contents.Append(indent).AppendLine("private static bool _defaultValid;");
+ contents.Append(indent).AppendLine($"private static {structureInfo.Name} _default;");
+ contents.AppendLine();
+ contents.Append(indent).AppendLine("/// ");
+ contents.Append(indent).AppendLine($"/// The default .");
+ contents.Append(indent).AppendLine("/// ");
+ contents.Append(indent).AppendLine($"public static {structureInfo.Name} Default");
+ contents.Append(indent).AppendLine("{");
+ indent += " ";
+ contents.Append(indent).AppendLine("get");
+ contents.Append(indent).AppendLine("{");
+ indent += " ";
+ contents.Append(indent).AppendLine("if (!_defaultValid)");
+ contents.Append(indent).AppendLine("{");
+ indent += " ";
+ contents.Append(indent).AppendLine("_defaultValid = true;");
+ contents.Append(indent).AppendLine("object obj = _default;");
+ contents.Append(indent).AppendLine($"FlaxEngine.Utils.InitStructure(obj, typeof({structureInfo.Name}));");
+ contents.Append(indent).AppendLine($"_default = ({structureInfo.Name})obj;");
+ indent = indent.Substring(0, indent.Length - 4);
+ contents.Append(indent).AppendLine("}");
+ contents.Append(indent).AppendLine("return _default;");
+ indent = indent.Substring(0, indent.Length - 4);
+ contents.Append(indent).AppendLine("}");
+ indent = indent.Substring(0, indent.Length - 4);
+ contents.Append(indent).AppendLine("}");
+ contents.AppendLine();
+ contents.Append(indent).AppendLine("[System.Runtime.Serialization.OnDeserializing]");
+ contents.Append(indent).AppendLine("internal void OnDeserializing(System.Runtime.Serialization.StreamingContext context)");
+ contents.Append(indent).AppendLine("{");
+ contents.Append(indent).AppendLine(" // Initialize structure with default values to replicate C++ deserialization behavior");
+ contents.Append(indent).AppendLine(" this = Default;");
+ contents.Append(indent).AppendLine("}");
+ }
+
// Nested types
foreach (var apiTypeInfo in structureInfo.Children)
{
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs
index 32a35d1e9..ceee5c814 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 = 15;
+ private const int CacheVersion = 16;
internal static void Write(BinaryWriter writer, string e)
{
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs
index e9c017692..2f3bb22f1 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs
@@ -1113,6 +1113,9 @@ namespace Flax.Build.Bindings
case "nopod":
desc.ForceNoPod = true;
break;
+ case "nodefault":
+ desc.NoDefault = true;
+ break;
case "attributes":
desc.Attributes = tag.Value;
break;
diff --git a/Source/Tools/Flax.Build/Bindings/StructureInfo.cs b/Source/Tools/Flax.Build/Bindings/StructureInfo.cs
index a3009d9aa..0fa157506 100644
--- a/Source/Tools/Flax.Build/Bindings/StructureInfo.cs
+++ b/Source/Tools/Flax.Build/Bindings/StructureInfo.cs
@@ -14,6 +14,7 @@ namespace Flax.Build.Bindings
public List Fields = new List();
public bool IsAutoSerialization;
public bool ForceNoPod;
+ public bool NoDefault;
public override bool IsStruct => true;
public override bool IsValueType => true;
@@ -72,6 +73,7 @@ namespace Flax.Build.Bindings
BindingsGenerator.Write(writer, Functions);
writer.Write(IsAutoSerialization);
writer.Write(ForceNoPod);
+ writer.Write(NoDefault);
base.Write(writer);
}
@@ -82,6 +84,7 @@ namespace Flax.Build.Bindings
Functions = BindingsGenerator.Read(reader, Functions);
IsAutoSerialization = reader.ReadBoolean();
ForceNoPod = reader.ReadBoolean();
+ NoDefault = reader.ReadBoolean();
base.Read(reader);
}