diff --git a/Source/Editor/CustomEditors/Values/ValueContainer.cs b/Source/Editor/CustomEditors/Values/ValueContainer.cs index 904d5bc09..3c360b4b3 100644 --- a/Source/Editor/CustomEditors/Values/ValueContainer.cs +++ b/Source/Editor/CustomEditors/Values/ValueContainer.cs @@ -250,7 +250,7 @@ namespace FlaxEditor.CustomEditors if (objA == null && objB is string objBStr && objBStr.Length == 0) return true; - return Newtonsoft.Json.Utilities.MiscellaneousUtils.ValueEquals(objA, objB); + return FlaxEngine.Json.JsonSerializer.ValueEquals(objA, objB); } /// diff --git a/Source/Engine/Serialization/JsonSerializer.cs b/Source/Engine/Serialization/JsonSerializer.cs index 0e4b88e50..f13be1e8f 100644 --- a/Source/Engine/Serialization/JsonSerializer.cs +++ b/Source/Engine/Serialization/JsonSerializer.cs @@ -1,6 +1,7 @@ // Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. using System; +using System.Collections; using System.Globalization; using System.IO; using System.Runtime.CompilerServices; @@ -23,7 +24,7 @@ namespace FlaxEngine.Json : base(sb, formatProvider) { Encoding = encoding; - } + } } partial class JsonSerializer @@ -174,7 +175,7 @@ namespace FlaxEngine.Json internal static JsonSerializerSettings CreateDefaultSettings(bool isManagedOnly) { - //Newtonsoft.Json.Utilities.MiscellaneousUtils.ValueEquals = ValueEquals; + Newtonsoft.Json.Utilities.MiscellaneousUtils.ValueEquals = ValueEquals; if (SerializationBinder is null) SerializationBinder = new(); var settings = new JsonSerializerSettings @@ -234,8 +235,66 @@ namespace FlaxEngine.Json /// True if both objects are equal, otherwise false. public static bool ValueEquals(object objA, object objB) { +#if false // Use default value comparision used by C# json serialization library return Newtonsoft.Json.Utilities.MiscellaneousUtils.ValueEquals(objA, objB); +#else + // Based on Newtonsoft.Json MiscellaneousUtils.ValueEquals but with customization for prefab object references diff + if (objA == objB) + return true; + if (objA == null || objB == null) + return false; + + // Special case when saving reference to prefab object and the objects are different but the point to the same prefab object + // In that case, skip saving reference as it's defined in prefab (will be populated via IdsMapping during deserialization) + if (objA is SceneObject sceneA && objB is SceneObject sceneB && sceneA.HasPrefabLink && sceneB.HasPrefabLink) + return sceneA.PrefabObjectID == sceneB.PrefabObjectID; + + // Comparing an Int32 and Int64 both of the same value returns false, make types the same then compare + if (objA.GetType() != objB.GetType()) + { + bool IsInteger(object value) + { + var type = value.GetType(); + return type == typeof(SByte) || + type == typeof(Byte) || + type == typeof(Int16) || + type == typeof(UInt16) || + type == typeof(Int32) || + type == typeof(UInt32) || + type == typeof(Int64) || + type == typeof(SByte) || + type == typeof(UInt64); + } + if (IsInteger(objA) && IsInteger(objB)) + return Convert.ToDecimal(objA, CultureInfo.CurrentCulture).Equals(Convert.ToDecimal(objB, CultureInfo.CurrentCulture)); + if ((objA is double || objA is float || objA is decimal) && (objB is double || objB is float || objB is decimal)) + return Mathd.NearEqual(Convert.ToDouble(objA, CultureInfo.CurrentCulture), Convert.ToDouble(objB, CultureInfo.CurrentCulture)); + return false; + } + + // Diff on collections + if (objA is IList aList && objB is IList bList) + { + if (aList.Count != bList.Count) + return false; + } + if (objA is IEnumerable aEnumerable && objB is IEnumerable bEnumerable) + { + var aEnumerator = aEnumerable.GetEnumerator(); + var bEnumerator = bEnumerable.GetEnumerator(); + using var aEnumerator1 = aEnumerator as IDisposable; + using var bEnumerator1 = bEnumerator as IDisposable; + while (aEnumerator.MoveNext()) + { + if (!bEnumerator.MoveNext() || !ValueEquals(aEnumerator.Current, bEnumerator.Current)) + return false; + } + return !bEnumerator.MoveNext(); + } + + return objA.Equals(objB); +#endif } /// diff --git a/Source/Platforms/DotNet/AOT/Newtonsoft.Json.dll b/Source/Platforms/DotNet/AOT/Newtonsoft.Json.dll index 24087dd29..83ecb3bf5 100644 --- a/Source/Platforms/DotNet/AOT/Newtonsoft.Json.dll +++ b/Source/Platforms/DotNet/AOT/Newtonsoft.Json.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22f78856541397ffe932df4db572d6a4ea3b4f3c843202f1b2b947a925cc2649 -size 541184 +oid sha256:8aadc5977413af81d4843f0ac6a417ec74d77e7224a06115ada40860ddd79608 +size 541696 diff --git a/Source/Platforms/DotNet/Newtonsoft.Json.dll b/Source/Platforms/DotNet/Newtonsoft.Json.dll index 52dc74149..e0b49ce89 100644 --- a/Source/Platforms/DotNet/Newtonsoft.Json.dll +++ b/Source/Platforms/DotNet/Newtonsoft.Json.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a3db675abf8c06f537cba70efa992723a93749e5771e24b8c911a90ccaea5a5 -size 604672 +oid sha256:5916f351729f50d48c9a58d40812925d3221e3db2684a932d3b52b697c113350 +size 605184 diff --git a/Source/Platforms/DotNet/Newtonsoft.Json.pdb b/Source/Platforms/DotNet/Newtonsoft.Json.pdb index 01e0fd1ce..42a55ea2c 100644 --- a/Source/Platforms/DotNet/Newtonsoft.Json.pdb +++ b/Source/Platforms/DotNet/Newtonsoft.Json.pdb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbb3be761269e1f66da40e85bf426841bbdaf6c9e5e8df1a5771e82d96aaf999 -size 239564 +oid sha256:84e95396873f9613eb18d1813b5d368888bf1ca6a4c40f6398d1963b7b4b1337 +size 239620 diff --git a/Source/Platforms/DotNet/Newtonsoft.Json.xml b/Source/Platforms/DotNet/Newtonsoft.Json.xml index 042a33d2f..644f46265 100644 --- a/Source/Platforms/DotNet/Newtonsoft.Json.xml +++ b/Source/Platforms/DotNet/Newtonsoft.Json.xml @@ -10054,7 +10054,20 @@ Helper utilities. - + + + Compares two objects data. + + The object a. + The object b. + True if both objects are equal, otherwise false. + + + + The custom value comparision callback. + + + The default implementation of the values comparision function. diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/NewtonsoftJson.cs b/Source/Tools/Flax.Build/Deps/Dependencies/NewtonsoftJson.cs index 36d33e755..03f811f73 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/NewtonsoftJson.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/NewtonsoftJson.cs @@ -57,22 +57,11 @@ namespace Flax.Deps.Dependencies // Default build GitCheckout(root, "flax-net80"); Deploy.VCEnvironment.BuildSolution(solutionPath, configuration, buildPlatform); - foreach (var platform in options.Platforms) { - BuildStarted(platform); - switch (platform) - { - case TargetPlatform.Windows: - case TargetPlatform.Linux: - case TargetPlatform.Mac: - { - foreach (var file in outputFileNames) - { - Utilities.FileCopy(Path.Combine(binFolder, file), Path.Combine(options.PlatformsFolder, "DotNet", file)); - } - break; - } - } + var platform = "JIT"; + Log.Info($"Building {GetType().Name} for {platform}"); + foreach (var file in outputFileNames) + Utilities.FileCopy(Path.Combine(binFolder, file), Path.Combine(options.PlatformsFolder, "DotNet", file)); } // AOT build (disabled codegen) @@ -82,24 +71,11 @@ namespace Flax.Deps.Dependencies Utilities.ReplaceInFile(Path.Combine(root, "Src", "Newtonsoft.Json", "Newtonsoft.Json.csproj"), "HAVE_REGEX;", ";"); Utilities.ReplaceInFile(Path.Combine(root, "Src", "Newtonsoft.Json", "Newtonsoft.Json.csproj"), "HAVE_TYPE_DESCRIPTOR;", ";"); Deploy.VCEnvironment.BuildSolution(solutionPath, configuration, buildPlatform); - foreach (var platform in options.Platforms) { - BuildStarted(platform); - switch (platform) - { - case TargetPlatform.UWP: - case TargetPlatform.XboxOne: - case TargetPlatform.XboxScarlett: - case TargetPlatform.PS4: - case TargetPlatform.PS5: - case TargetPlatform.Switch: - case TargetPlatform.iOS: - { - var file = "Newtonsoft.Json.dll"; - Utilities.FileCopy(Path.Combine(binFolder, file), Path.Combine(options.PlatformsFolder, "DotNet/AOT", file)); - break; - } - } + var platform = "AOT"; + Log.Info($"Building {GetType().Name} for {platform}"); + var file = "Newtonsoft.Json.dll"; + Utilities.FileCopy(Path.Combine(binFolder, file), Path.Combine(options.PlatformsFolder, "DotNet/AOT", file)); } } }