From ed4eeee647830c11e3f12b4670f344aae2c943c4 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 27 Apr 2021 10:14:19 +0200 Subject: [PATCH] Fix undo for custom serialized objects (eg. LocalizedString) --- Source/Editor/History/UndoActionObject.cs | 22 +++++++++++++++++++ Source/Editor/SceneGraph/SceneGraphNode.cs | 1 + Source/Editor/Undo/UndoActionBase.cs | 16 +++----------- Source/Engine/Serialization/JsonConverters.cs | 7 ++++++ 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/Source/Editor/History/UndoActionObject.cs b/Source/Editor/History/UndoActionObject.cs index cac710bff..a87637f4f 100644 --- a/Source/Editor/History/UndoActionObject.cs +++ b/Source/Editor/History/UndoActionObject.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using FlaxEditor.Utilities; using FlaxEngine; +using Newtonsoft.Json; +using JsonSerializer = FlaxEngine.Json.JsonSerializer; namespace FlaxEditor.History { @@ -114,6 +116,8 @@ namespace FlaxEditor.History public object TargetInstance; } + internal static JsonSerializerSettings JsonSettings; + // For objects that cannot be referenced in undo action like: FlaxEngine.Object or SceneGraphNode we store them in DataStorage, // otherwise here: private readonly object TargetInstance; @@ -177,6 +181,24 @@ namespace FlaxEditor.History }; } + /// + public override DataStorage Data + { + protected set + { + // Inject objects typename serialization to prevent data type mismatch when loading from saved state + var settings = JsonSettings; + if (settings == null) + { + settings = JsonSerializer.CreateDefaultSettings(false); + settings.TypeNameHandling = TypeNameHandling.All; + JsonSettings = settings; + } + _data = JsonConvert.SerializeObject(value, Formatting.Indented, settings); + //Editor.Log(_data); + } + } + /// public override string ActionString { get; } diff --git a/Source/Editor/SceneGraph/SceneGraphNode.cs b/Source/Editor/SceneGraph/SceneGraphNode.cs index 76327918d..6cf83647a 100644 --- a/Source/Editor/SceneGraph/SceneGraphNode.cs +++ b/Source/Editor/SceneGraph/SceneGraphNode.cs @@ -374,6 +374,7 @@ namespace FlaxEditor.SceneGraph /// /// Gets or sets the node state. /// + [NoSerialize] public virtual StateData State { get => throw new NotImplementedException(); diff --git a/Source/Editor/Undo/UndoActionBase.cs b/Source/Editor/Undo/UndoActionBase.cs index 5de052a45..6648096c6 100644 --- a/Source/Editor/Undo/UndoActionBase.cs +++ b/Source/Editor/Undo/UndoActionBase.cs @@ -4,7 +4,6 @@ using System; using FlaxEditor.SceneGraph; using FlaxEngine; using Newtonsoft.Json; -using JsonSerializer = FlaxEngine.Json.JsonSerializer; namespace FlaxEditor { @@ -28,7 +27,6 @@ namespace FlaxEditor var id = Guid.Parse((string)reader.Value); return SceneGraphFactory.FindNode(id); } - return null; } @@ -56,19 +54,11 @@ namespace FlaxEditor /// /// Gets or sets the serialized undo data. /// - /// - /// The data. - /// [NoSerialize] - public TData Data + public virtual TData Data { - get => JsonConvert.DeserializeObject(_data, JsonSerializer.Settings); - protected set => _data = JsonConvert.SerializeObject(value, Formatting.None, JsonSerializer.Settings); - /*protected set - { - _data = JsonConvert.SerializeObject(value, Formatting.Indented, JsonSerializer.Settings); - Debug.Info(_data); - }*/ + get => JsonConvert.DeserializeObject(_data, FlaxEngine.Json.JsonSerializer.Settings); + protected set => _data = JsonConvert.SerializeObject(value, Formatting.None, FlaxEngine.Json.JsonSerializer.Settings); } /// diff --git a/Source/Engine/Serialization/JsonConverters.cs b/Source/Engine/Serialization/JsonConverters.cs index 4403487a0..2ebf16a79 100644 --- a/Source/Engine/Serialization/JsonConverters.cs +++ b/Source/Engine/Serialization/JsonConverters.cs @@ -236,6 +236,13 @@ namespace FlaxEngine.Json else { writer.WriteStartObject(); +#if FLAX_EDITOR + if ((serializer.TypeNameHandling & TypeNameHandling.Objects) == TypeNameHandling.Objects) + { + writer.WritePropertyName("$type"); + writer.WriteValue("FlaxEngine.LocalizedString, FlaxEngine.CSharp"); + } +#endif writer.WritePropertyName("Id"); writer.WriteValue(str.Id); writer.WritePropertyName("Value");