From d5075d845c674183cb00e61045e1e4d35f237096 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 23 Nov 2023 17:37:55 +0100 Subject: [PATCH] Fix content storage usage with relative paths #1966 --- Source/Engine/Content/BinaryAsset.cpp | 30 ++++++++++++------- Source/Engine/Content/Content.cpp | 9 +++--- .../Content/Storage/ContentStorageManager.cpp | 11 +++++++ .../Content/Storage/ContentStorageManager.h | 3 ++ 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/Source/Engine/Content/BinaryAsset.cpp b/Source/Engine/Content/BinaryAsset.cpp index b04603a96..9519f73df 100644 --- a/Source/Engine/Content/BinaryAsset.cpp +++ b/Source/Engine/Content/BinaryAsset.cpp @@ -323,26 +323,29 @@ bool BinaryAsset::SaveToAsset(const StringView& path, AssetInitData& data, bool { // Ensure path is in a valid format String pathNorm(path); - FileSystem::NormalizePath(pathNorm); + ContentStorageManager::FormatPath(pathNorm); + const StringView filePath = pathNorm; // Find target storage container and the asset - auto storage = ContentStorageManager::TryGetStorage(pathNorm); - auto asset = Content::GetAsset(pathNorm); + auto storage = ContentStorageManager::TryGetStorage(filePath); + auto asset = Content::GetAsset(filePath); auto binaryAsset = dynamic_cast(asset); if (asset && !binaryAsset) { LOG(Warning, "Cannot write to the non-binary asset location."); return true; } + if (!binaryAsset && !storage && FileSystem::FileExists(filePath)) + { + // Force-resolve storage (asset at that path could be not yet loaded into registry) + storage = ContentStorageManager::GetStorage(filePath); + } // Check if can perform write operation to the asset container - if (storage) + if (storage && !storage->AllowDataModifications()) { - if (!storage->AllowDataModifications()) - { - LOG(Warning, "Cannot write to the asset storage container."); - return true; - } + LOG(Warning, "Cannot write to the asset storage container."); + return true; } // Initialize data container @@ -352,6 +355,11 @@ bool BinaryAsset::SaveToAsset(const StringView& path, AssetInitData& data, bool // Use the same asset ID data.Header.ID = binaryAsset->GetID(); } + else if (storage && storage->GetEntriesCount()) + { + // Use the same file ID + data.Header.ID = storage->GetEntry(0).ID; + } else { // Randomize ID @@ -373,8 +381,8 @@ bool BinaryAsset::SaveToAsset(const StringView& path, AssetInitData& data, bool } else { - ASSERT(pathNorm.HasChars()); - result = FlaxStorage::Create(pathNorm, data, silentMode); + ASSERT(filePath.HasChars()); + result = FlaxStorage::Create(filePath, data, silentMode); } if (binaryAsset) binaryAsset->_isSaving = false; diff --git a/Source/Engine/Content/Content.cpp b/Source/Engine/Content/Content.cpp index bd27abc5a..910e16d66 100644 --- a/Source/Engine/Content/Content.cpp +++ b/Source/Engine/Content/Content.cpp @@ -449,18 +449,19 @@ Asset* Content::LoadAsync(const StringView& path, const ScriptingTypeHandle& typ { // Ensure path is in a valid format String pathNorm(path); - StringUtils::PathRemoveRelativeParts(pathNorm); + ContentStorageManager::FormatPath(pathNorm); + const StringView filePath = pathNorm; #if USE_EDITOR - if (!FileSystem::FileExists(pathNorm)) + if (!FileSystem::FileExists(filePath)) { - LOG(Error, "Missing file \'{0}\'", pathNorm); + LOG(Error, "Missing file \'{0}\'", filePath); return nullptr; } #endif AssetInfo assetInfo; - if (GetAssetInfo(pathNorm, assetInfo)) + if (GetAssetInfo(filePath, assetInfo)) { return LoadAsync(assetInfo.ID, type); } diff --git a/Source/Engine/Content/Storage/ContentStorageManager.cpp b/Source/Engine/Content/Storage/ContentStorageManager.cpp index d3e18e9d0..61e73a3f2 100644 --- a/Source/Engine/Content/Storage/ContentStorageManager.cpp +++ b/Source/Engine/Content/Storage/ContentStorageManager.cpp @@ -6,6 +6,7 @@ #include "Engine/Core/Log.h" #include "Engine/Engine/Engine.h" #include "Engine/Engine/EngineService.h" +#include "Engine/Engine/Globals.h" #include "Engine/Platform/FileSystem.h" #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Threading/TaskGraph.h" @@ -185,6 +186,16 @@ void ContentStorageManager::EnsureUnlocked() Locker.Unlock(); } +void ContentStorageManager::FormatPath(String& path) +{ + StringUtils::PathRemoveRelativeParts(path); + if (FileSystem::IsRelative(path)) + { + // Convert local-project paths into absolute format which is used by Content Storage system + path = Globals::ProjectFolder / path; + } +} + bool ContentStorageManager::IsFlaxStoragePath(const String& path) { auto extension = FileSystem::GetExtension(path).ToLower(); diff --git a/Source/Engine/Content/Storage/ContentStorageManager.h b/Source/Engine/Content/Storage/ContentStorageManager.h index c615632e9..84a6dc07e 100644 --- a/Source/Engine/Content/Storage/ContentStorageManager.h +++ b/Source/Engine/Content/Storage/ContentStorageManager.h @@ -75,6 +75,9 @@ public: /// static void EnsureUnlocked(); + // Formats path into valid format used by the storage system (normalized and absolute). + static void FormatPath(String& path); + public: /// /// Determines whether the specified path can be a binary asset file (based on it's extension).