From 969053a2407b271ac3a5fb9a7c28dfd7c1382b48 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 16 Feb 2023 14:32:52 +0100 Subject: [PATCH] Add `JsonAsset.Save` to fix saving new tag #885 --- .../Editor/CustomEditors/Editors/TagEditor.cs | 4 +- Source/Engine/Content/JsonAsset.cpp | 59 +++++++++- Source/Engine/Content/JsonAsset.h | 11 ++ .../Localization/LocalizedStringTable.cpp | 107 +++++++----------- .../Localization/LocalizedStringTable.h | 12 +- 5 files changed, 105 insertions(+), 88 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs index 8a4333a9b..948663892 100644 --- a/Source/Editor/CustomEditors/Editors/TagEditor.cs +++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs @@ -174,9 +174,7 @@ namespace FlaxEditor.CustomEditors.Editors for (int i = 0; i < subInputs.Length; i++) { if (string.IsNullOrEmpty(subInputs[i])) - { continue; - } // Check all entered subtags and create any that dont exist for (int j = 0; j <= i; j++) @@ -296,6 +294,7 @@ namespace FlaxEditor.CustomEditors.Editors settingsObj.Tags.Add(tagName); settingsObj.Tags.Sort(); settingsAsset.SetInstance(settingsObj); + settingsAsset.Save(); // Reload editor window to reflect new tag assetWindow?.RefreshAsset(); @@ -417,7 +416,6 @@ namespace FlaxEditor.CustomEditors.Editors { if (!uniqueText) return; - OnAddTagButtonClicked(nameTextBox.Text, tree, nameTextBox, addTagDropPanel, pickerData); }; diff --git a/Source/Engine/Content/JsonAsset.cpp b/Source/Engine/Content/JsonAsset.cpp index 6fdfca74e..2e1dc2f0e 100644 --- a/Source/Engine/Content/JsonAsset.cpp +++ b/Source/Engine/Content/JsonAsset.cpp @@ -37,12 +37,8 @@ String JsonAssetBase::GetData() const if (Data == nullptr) return String::Empty; PROFILE_CPU_NAMED("JsonAsset.GetData"); - - // Get serialized data rapidjson_flax::StringBuffer buffer; - rapidjson_flax::Writer writer(buffer); - Data->Accept(writer); - + OnGetData(buffer); return String((const char*)buffer.GetString(), (int32)buffer.GetSize()); } @@ -83,6 +79,12 @@ bool JsonAssetBase::Init(const StringView& dataTypeName, const StringAnsiView& d return loadAsset() != LoadResult::Ok; } +void JsonAssetBase::OnGetData(rapidjson_flax::StringBuffer& buffer) const +{ + PrettyJsonWriter writerObj(buffer); + Data->Accept(writerObj.GetWriter()); +} + const String& JsonAssetBase::GetPath() const { #if USE_EDITOR @@ -144,6 +146,53 @@ void JsonAssetBase::GetReferences(const StringAnsiView& json, Array& outpu FindIds(document, output); } +bool JsonAssetBase::Save(const StringView& path) +{ + // Validate state + if (WaitForLoaded()) + { + LOG(Error, "Asset loading failed. Cannot save it."); + return true; + } + if (IsVirtual() && path.IsEmpty()) + { + LOG(Error, "To save virtual asset asset you need to specify the target asset path location."); + return true; + } + ScopeLock lock(Locker); + + // Serialize to json file + rapidjson_flax::StringBuffer buffer; + PrettyJsonWriter writerObj(buffer); + JsonWriter& writer = writerObj; + writer.StartObject(); + { + // Json resource header + writer.JKEY("ID"); + writer.Guid(GetID()); + writer.JKEY("TypeName"); + writer.String(DataTypeName); + writer.JKEY("EngineBuild"); + writer.Int(FLAXENGINE_VERSION_BUILD); + + // Json resource data + rapidjson_flax::StringBuffer dataBuffer; + OnGetData(dataBuffer); + writer.JKEY("Data"); + writer.RawValue(dataBuffer.GetString(), (int32)dataBuffer.GetSize()); + } + writer.EndObject(); + + // Save json to file + if (File::WriteAllBytes(path.HasChars() ? path : GetPath(), (byte*)buffer.GetString(), (int32)buffer.GetSize())) + { + LOG(Error, "Cannot save \'{0}\'", ToString()); + return true; + } + + return false; +} + void JsonAssetBase::GetReferences(Array& output) const { if (Data == nullptr) diff --git a/Source/Engine/Content/JsonAsset.h b/Source/Engine/Content/JsonAsset.h index 9fca675ee..ca52ac86b 100644 --- a/Source/Engine/Content/JsonAsset.h +++ b/Source/Engine/Content/JsonAsset.h @@ -72,8 +72,19 @@ public: /// The Json string. /// The output list of object IDs references by the asset (appended, not cleared). API_FUNCTION() static void GetReferences(const StringAnsiView& json, API_PARAM(Out) Array& output); + + /// + /// Saves this asset to the file. Supported only in Editor. + /// + /// The custom asset path to use for the saving. Use empty value to save this asset to its own storage location. Can be used to duplicate asset. Must be specified when saving virtual asset. + /// True if cannot save data, otherwise false. + API_FUNCTION() bool Save(const StringView& path = StringView::Empty); #endif +protected: + // Gets the serialized Json data (from runtime state). + virtual void OnGetData(rapidjson_flax::StringBuffer& buffer) const; + public: // [Asset] const String& GetPath() const override; diff --git a/Source/Engine/Localization/LocalizedStringTable.cpp b/Source/Engine/Localization/LocalizedStringTable.cpp index 63a364e77..9c01736bd 100644 --- a/Source/Engine/Localization/LocalizedStringTable.cpp +++ b/Source/Engine/Localization/LocalizedStringTable.cpp @@ -55,75 +55,6 @@ String LocalizedStringTable::GetPluralString(const String& id, int32 n) const return String::Format(result.GetText(), n); } -#if USE_EDITOR - -bool LocalizedStringTable::Save(const StringView& path) -{ - // Validate state - if (WaitForLoaded()) - { - LOG(Error, "Asset loading failed. Cannot save it."); - return true; - } - if (IsVirtual() && path.IsEmpty()) - { - LOG(Error, "To save virtual asset asset you need to specify the target asset path location."); - return true; - } - - ScopeLock lock(Locker); - - // Serialize data - rapidjson_flax::StringBuffer outputData; - PrettyJsonWriter writerObj(outputData); - JsonWriter& writer = writerObj; - writer.StartObject(); - { - writer.JKEY("Locale"); - writer.String(Locale); - - if (FallbackTable.GetID().IsValid()) - { - writer.JKEY("FallbackTable"); - writer.Guid(FallbackTable.GetID()); - } - - writer.JKEY("Entries"); - writer.StartObject(); - for (auto& e : Entries) - { - writer.Key(e.Key); - if (e.Value.Count() == 1) - { - writer.String(e.Value[0]); - } - else - { - writer.StartArray(); - for (auto& q : e.Value) - writer.String(q); - writer.EndArray(); - } - } - writer.EndObject(); - } - writer.EndObject(); - - // Save asset -#if COMPILE_WITH_ASSETS_IMPORTER - const bool saveResult = CreateJson::Create(path.HasChars() ? path : StringView(GetPath()), outputData, TypeName); - if (saveResult) -#endif - { - LOG(Error, "Cannot save \'{0}\'", ToString()); - return true; - } - - return false; -} - -#endif - Asset::LoadResult LocalizedStringTable::loadAsset() { // Base @@ -170,3 +101,41 @@ void LocalizedStringTable::unload(bool isReloading) FallbackTable = nullptr; Entries.Clear(); } + +void LocalizedStringTable::OnGetData(rapidjson_flax::StringBuffer& buffer) const +{ + PrettyJsonWriter writerObj(buffer); + JsonWriter& writer = writerObj; + writer.StartObject(); + { + writer.JKEY("Locale"); + writer.String(Locale); + + if (FallbackTable.GetID().IsValid()) + { + writer.JKEY("FallbackTable"); + writer.Guid(FallbackTable.GetID()); + } + + writer.JKEY("Entries"); + writer.StartObject(); + for (auto& e : Entries) + { + writer.Key(e.Key); + if (e.Value.Count() == 1) + { + writer.String(e.Value[0]); + } + else + { + writer.StartArray(); + for (auto& q : e.Value) + writer.String(q); + writer.EndArray(); + } + } + writer.EndObject(); + } + writer.EndObject(); +} + diff --git a/Source/Engine/Localization/LocalizedStringTable.h b/Source/Engine/Localization/LocalizedStringTable.h index e52b5cc3f..4024d5d3a 100644 --- a/Source/Engine/Localization/LocalizedStringTable.h +++ b/Source/Engine/Localization/LocalizedStringTable.h @@ -61,19 +61,9 @@ public: /// The localized text. API_FUNCTION() String GetPluralString(const String& id, int32 n) const; -#if USE_EDITOR - - /// - /// Saves this asset to the file. Supported only in Editor. - /// - /// The custom asset path to use for the saving. Use empty value to save this asset to its own storage location. Can be used to duplicate asset. Must be specified when saving virtual asset. - /// True if cannot save data, otherwise false. - API_FUNCTION() bool Save(const StringView& path = StringView::Empty); - -#endif - protected: // [JsonAssetBase] LoadResult loadAsset() override; void unload(bool isReloading) override; + void OnGetData(rapidjson_flax::StringBuffer& buffer) const override; };