Add support for configuring default Archive File Search Mode through a Cache Var (#5668)
* Renamed ArchiveLocationPriority enum to FileSearchPriority and made it a proper enum class Added an ArchiveVars.cpp which checks the a new define: `LY_ARCHIVE_FILE_SEARCH_MODE_DEFAULT` That define represents the default value to use for the Archive system search mode Moved the FileSearchLocation enum to the ArchiveVars.h header Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the AssetBundleComponent to use AZ::IO::Path for level dirs Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Added a LY_ARCHIVE_FILE_SEARCH_MODE cache variable The Cache Variable default value is to Archive File Search Mode to PakOnly in Release. This can be overridden using a value for all configurations by specifying a number of 0, 1 or 2. Alternatively a generator expression can be used to set the Archive File Search Mode in specific configurations. For example to set the FileSearchMode to 1 in profile and 2 in release the following LY_ARCHIVE_FILE_SEARCH_MODE value can be used `$<$<CONFIG:profile>:1>$<$<CONFIG:release>:2>` Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated AssetBundler(Batch) VS Debugger arguments to populate the project-path optoin if a single project is configured. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Add support for serializing older versions of the AssetBundleManifest This is done by attaching the "ObjectStreamWriteElementOverride" attribute to the AssetBundleManifest reflection. That attribute contains a function which outputs an older serialized version of the AssetBundleManifest based on the `m_bundleVersion` member value. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * AZStd::variant Serialization fix The AttributeData<T> type is no longer suitable for storing the ObjectStreamWriterOverrideCB function Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
489877b82a
commit
9d22c98c26
@@ -1128,7 +1128,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename)
|
||||
const QString oldLevelPattern = QDir(oldLevelFolder).absoluteFilePath("*.*");
|
||||
const QString oldLevelName = Path::GetFile(GetLevelPathName());
|
||||
const QString oldLevelXml = Path::ReplaceExtension(oldLevelName, "xml");
|
||||
AZ::IO::ArchiveFileIterator findHandle = pIPak->FindFirst(oldLevelPattern.toUtf8().data(), AZ::IO::IArchive::eFileSearchType_AllowOnDiskAndInZips);
|
||||
AZ::IO::ArchiveFileIterator findHandle = pIPak->FindFirst(oldLevelPattern.toUtf8().data(), AZ::IO::FileSearchLocation::Any);
|
||||
if (findHandle)
|
||||
{
|
||||
do
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/IO/Path/Path_fwd.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/containers/bitset.h>
|
||||
#include <AzCore/Outcome/Outcome.h>
|
||||
@@ -129,7 +130,8 @@ namespace AZ
|
||||
/// Remove a catalog from our delta list and rebuild the catalog from remaining items
|
||||
virtual bool RemoveDeltaCatalog(AZStd::shared_ptr<AzFramework::AssetRegistry> /*deltaCatalog*/) { return true; }
|
||||
/// Creates a manifest with the given DeltaCatalog name
|
||||
virtual bool CreateBundleManifest(const AZStd::string& /*deltaCatalogPath*/, const AZStd::vector<AZStd::string>& /*dependentBundleNames*/, const AZStd::string& /*fileDirectory*/, int /*bundleVersion*/, const AZStd::vector<AZStd::string>& /*levelDirs*/) { return false; }
|
||||
virtual bool CreateBundleManifest(const AZStd::string& /*deltaCatalogPath*/, const AZStd::vector<AZStd::string>& /*dependentBundleNames*/,
|
||||
const AZStd::string& /*fileDirectory*/, int /*bundleVersion*/, const AZStd::vector<AZ::IO::Path>& /*levelDirs*/) { return false; }
|
||||
/// Creates an instance of a registry containing info for just the specified files, and writes it out to a file at the specified path
|
||||
virtual bool CreateDeltaCatalog(const AZStd::vector<AZStd::string>& /*files*/, const AZStd::string& /*filePath*/) { return false; }
|
||||
|
||||
|
||||
@@ -54,12 +54,8 @@ namespace AZStd
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
//template<class T>
|
||||
//class ScriptProperty;
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
|
||||
template <class ValueType>
|
||||
void SetupClassElementFromType(SerializeContext::ClassElement& classElement)
|
||||
{
|
||||
@@ -86,8 +82,7 @@ namespace AZ
|
||||
{
|
||||
auto uuid = AzTypeInfo<ValueType>::Uuid();
|
||||
|
||||
using ContainerType = AttributeContainerType<AZ::TypeId>;
|
||||
classElement.m_attributes.emplace_back(AZ_CRC("EnumType", 0xb177e1b5), CreateModuleAttribute<ContainerType>(AZStd::move(uuid)));
|
||||
classElement.m_attributes.emplace_back(AZ_CRC("EnumType", 0xb177e1b5), CreateModuleAttribute(AZStd::move(uuid)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -648,7 +643,6 @@ namespace AZ
|
||||
|
||||
// Register our key type within an lvalue to rvalue wrapper as an attribute
|
||||
AZ::TypeId uuid = azrtti_typeid<WrappedKeyType>();
|
||||
using ContainerType = AttributeContainerType<AZ::TypeId>;
|
||||
|
||||
/**
|
||||
* This should technically bind the reference value from the GetCurrentSerializeContextModule() call
|
||||
@@ -658,7 +652,7 @@ namespace AZ
|
||||
*/
|
||||
m_classElement.m_attributes.set_allocator(AZStdFunctorAllocator([]() -> IAllocatorAllocate& { return GetCurrentSerializeContextModule().GetAllocator(); }));
|
||||
|
||||
m_classElement.m_attributes.emplace_back(AZ_CRC("KeyType", 0x15bc5303), CreateModuleAttribute<ContainerType>(AZStd::move(uuid)));
|
||||
m_classElement.m_attributes.emplace_back(AZ_CRC("KeyType", 0x15bc5303), CreateModuleAttribute(AZStd::move(uuid)));
|
||||
}
|
||||
|
||||
// Reflect our wrapped key and value types to serializeContext so that may later be used
|
||||
|
||||
@@ -1643,12 +1643,15 @@ namespace AZ
|
||||
m_writeElementResultStack.push_back(WriteElement(ptr, classData, classElement));
|
||||
return m_writeElementResultStack.back();
|
||||
};
|
||||
auto closeElementCB = [this, classData]()
|
||||
auto closeElementCB = [this, classTypeId = classData->m_typeId]()
|
||||
{
|
||||
if (m_writeElementResultStack.empty())
|
||||
{
|
||||
AZ_UNUSED(classData); // Prevent unused warning in release builds
|
||||
AZ_Error("Serialize", false, "CloseElement is attempted to be called without a corresponding WriteElement when writing class %s", classData->m_name);
|
||||
// ClassData could be dangling pointer if it was unreflected by the ObjectStreamWriteOverrideCB
|
||||
// So use the classTypeId instead
|
||||
AZ_UNUSED(classTypeId);
|
||||
AZ_Error("Serialize", false, "CloseElement is attempted to be called without a corresponding WriteElement when writing class %s",
|
||||
classTypeId.ToString<AZStd::fixed_string<AZ::TypeId::MaxStringBuffer>>().c_str());
|
||||
return true;
|
||||
}
|
||||
if (m_writeElementResultStack.back())
|
||||
@@ -1665,16 +1668,14 @@ namespace AZ
|
||||
SerializeContext::ENUM_ACCESS_FOR_READ,
|
||||
&m_errorLogger
|
||||
);
|
||||
ObjectStreamWriteOverrideCB writeCB;
|
||||
if (objectStreamWriteOverrideCB.Read<ObjectStreamWriteOverrideCB>(writeCB))
|
||||
if (objectStreamWriteOverrideCB.Invoke<void>(callContext, objectPtr, *classData, classElement))
|
||||
{
|
||||
writeCB(callContext, objectPtr, *classData, classElement);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto objectStreamError = AZStd::string::format("Unable to invoke ObjectStream Write Element Override for class element %s of class data %s",
|
||||
classElement->m_name ? classElement->m_name : "", classData->m_name);
|
||||
classElement && classElement->m_name ? classElement->m_name : "", classData->m_name);
|
||||
m_errorLogger.ReportError(objectStreamError.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace AZ
|
||||
|
||||
using AttributePtr = AZStd::shared_ptr<Attribute>;
|
||||
using AttributeSharedPair = AZStd::pair<AttributeId, AttributePtr>;
|
||||
template <typename ContainerType, typename T>
|
||||
template <typename T, typename ContainerType = AttributeContainerType<T>>
|
||||
AttributePtr CreateModuleAttribute(T&& attrValue);
|
||||
|
||||
/**
|
||||
@@ -540,6 +540,7 @@ namespace AZ
|
||||
*/
|
||||
struct ClassElement
|
||||
{
|
||||
AZ_TYPE_INFO(ClassElement, "{7D386902-A1D9-4525-8284-F68435FE1D05}");
|
||||
enum Flags
|
||||
{
|
||||
FLG_POINTER = (1 << 0), ///< Element is stored as pointer (it's not a value).
|
||||
@@ -563,22 +564,22 @@ namespace AZ
|
||||
void ClearAttributes();
|
||||
Attribute* FindAttribute(AttributeId attributeId) const;
|
||||
|
||||
const char* m_name; ///< Used in XML output and debugging purposes
|
||||
u32 m_nameCrc; ///< CRC32 of m_name
|
||||
Uuid m_typeId;
|
||||
size_t m_dataSize;
|
||||
size_t m_offset;
|
||||
const char* m_name{ "" }; ///< Used in XML output and debugging purposes
|
||||
u32 m_nameCrc{}; ///< CRC32 of m_name
|
||||
Uuid m_typeId = AZ::TypeId::CreateNull();
|
||||
size_t m_dataSize{};
|
||||
size_t m_offset{};
|
||||
|
||||
IRttiHelper* m_azRtti; ///< Interface used to support RTTI.
|
||||
IRttiHelper* m_azRtti{}; ///< Interface used to support RTTI.
|
||||
GenericClassInfo* m_genericClassInfo = nullptr; ///< Valid when the generic class is set. So you don't search for the actual type in the class register.
|
||||
Edit::ElementData* m_editData; ///< Pointer to edit data (generated by EditContext).
|
||||
Edit::ElementData* m_editData{}; ///< Pointer to edit data (generated by EditContext).
|
||||
AZStd::vector<AttributeSharedPair, AZStdFunctorAllocator> m_attributes{
|
||||
AZStdFunctorAllocator([]() -> IAllocatorAllocate& { return AZ::AllocatorInstance<AZ::SystemAllocator>::Get(); })
|
||||
}; ///< Attributes attached to ClassElement. Lambda is required here as AZStdFunctorAllocator expects a function pointer
|
||||
///< that returns an IAllocatorAllocate& and the AZ::AllocatorInstance<AZ::SystemAllocator>::Get returns an AZ::SystemAllocator&
|
||||
/// which while it inherits from IAllocatorAllocate, does not work as function pointers do not support covariant return types
|
||||
AttributeOwnership m_attributeOwnership = AttributeOwnership::Parent;
|
||||
int m_flags; ///<
|
||||
int m_flags{}; ///<
|
||||
};
|
||||
typedef AZStd::vector<ClassElement> ClassElementArray;
|
||||
|
||||
@@ -589,6 +590,8 @@ namespace AZ
|
||||
class ClassData
|
||||
{
|
||||
public:
|
||||
AZ_TYPE_INFO(ClassData, "{20EB8E2E-D807-4039-84E2-CE37D7647CD4}");
|
||||
|
||||
ClassData();
|
||||
~ClassData() { ClearAttributes(); }
|
||||
ClassData(ClassData&&) = default;
|
||||
@@ -1040,6 +1043,7 @@ namespace AZ
|
||||
*/
|
||||
struct EnumerateInstanceCallContext
|
||||
{
|
||||
AZ_TYPE_INFO(EnumerateInstanceCallContext, "{FCC1DB4B-72BD-4D78-9C23-C84B91589D33}");
|
||||
EnumerateInstanceCallContext(const BeginElemEnumCB& beginElemCB, const EndElemEnumCB& endElemCB, const SerializeContext* context, unsigned int accessflags, ErrorHandler* errorHandler);
|
||||
|
||||
BeginElemEnumCB m_beginElemCB; ///< Optional callback when entering an element's hierarchy.
|
||||
@@ -2539,7 +2543,7 @@ namespace AZ
|
||||
/// associated with current module
|
||||
/// @param attrValue value to store within the attribute
|
||||
/// @param ContainerType second parameter which is used for function parameter deduction
|
||||
template <typename ContainerType, typename T>
|
||||
template <typename T, typename ContainerType>
|
||||
AttributePtr CreateModuleAttribute(T&& attrValue)
|
||||
{
|
||||
IAllocatorAllocate& moduleAllocator = GetCurrentSerializeContextModule().GetAllocator();
|
||||
|
||||
@@ -433,9 +433,7 @@ namespace AZ
|
||||
m_classData.m_attributes.set_allocator(AZStd::move(dllAllocator));
|
||||
|
||||
// Create the ObjectStreamWriteOverrideCB in the current module
|
||||
using ContainerType = AttributeData<AZStd::function<void(SerializeContext::EnumerateInstanceCallContext&,
|
||||
const void*, const SerializeContext::ClassData&, const SerializeContext::ClassElement*)>>;
|
||||
m_classData.m_attributes.emplace_back(AZ_CRC("ObjectStreamWriteElementOverride", 0x35eb659f), CreateModuleAttribute<ContainerType>(&ObjectStreamWriter));
|
||||
m_classData.m_attributes.emplace_back(AZ_CRC("ObjectStreamWriteElementOverride", 0x35eb659f), CreateModuleAttribute(&ObjectStreamWriter));
|
||||
}
|
||||
|
||||
SerializeContext::ClassData* GetClassData() override
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include <AzFramework/Archive/Archive.h>
|
||||
#include <AzFramework/Archive/NestedArchive.h>
|
||||
#include <AzFramework/Archive/ArchiveBus.h>
|
||||
#include <AzFramework/Archive/ArchiveVars.h>
|
||||
#include <AzFramework/Archive/MissingFileReport.h>
|
||||
#include <AzFramework/Archive/ZipDirFind.h>
|
||||
#include <AzFramework/Archive/ZipDirCacheFactory.h>
|
||||
@@ -43,8 +42,10 @@
|
||||
|
||||
namespace AZ::IO
|
||||
{
|
||||
AZ_CVAR(int, sys_PakPriority, aznumeric_cast<int>(ArchiveVars{}.nPriority), nullptr, AZ::ConsoleFunctorFlags::Null,
|
||||
"If set to 1, tells Archive to try to open the file in pak first, then go to file system");
|
||||
AZ_CVAR(int, sys_PakPriority, aznumeric_cast<int>(ArchiveVars{}.m_fileSearchPriority), nullptr, AZ::ConsoleFunctorFlags::Null,
|
||||
"If set to 0, tells Archive to try to open the file on the file system first othewise check mounted paks.\n"
|
||||
"If set to 1, tells Archive to try to open the file in pak first, then go to file system.\n"
|
||||
"If set to 2, tells the Archive to only open files from the pak");
|
||||
AZ_CVAR(int, sys_PakMessageInvalidFileAccess, ArchiveVars{}.nMessageInvalidFileAccess, nullptr, AZ::ConsoleFunctorFlags::Null,
|
||||
"Message Box synchronous file access when in game");
|
||||
|
||||
@@ -437,9 +438,9 @@ namespace AZ::IO
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool Archive::IsFileExist(AZStd::string_view sFilename, EFileSearchLocation fileLocation)
|
||||
bool Archive::IsFileExist(AZStd::string_view sFilename, FileSearchLocation fileLocation)
|
||||
{
|
||||
const AZ::IO::ArchiveLocationPriority nVarPakPriority = GetPakPriority();
|
||||
const AZ::IO::FileSearchPriority nVarPakPriority = GetPakPriority();
|
||||
|
||||
auto szFullPath = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(sFilename);
|
||||
if (!szFullPath)
|
||||
@@ -450,25 +451,25 @@ namespace AZ::IO
|
||||
|
||||
switch(fileLocation)
|
||||
{
|
||||
case IArchive::eFileLocation_Any:
|
||||
case FileSearchLocation::Any:
|
||||
// Search for file based on pak priority
|
||||
switch (nVarPakPriority)
|
||||
{
|
||||
case ArchiveLocationPriority::ePakPriorityFileFirst:
|
||||
case FileSearchPriority::FileFirst:
|
||||
return FileIOBase::GetDirectInstance()->Exists(szFullPath->c_str()) || FindPakFileEntry(szFullPath->Native());
|
||||
case ArchiveLocationPriority::ePakPriorityPakFirst:
|
||||
case FileSearchPriority::PakFirst:
|
||||
return FindPakFileEntry(szFullPath->Native()) || IO::FileIOBase::GetDirectInstance()->Exists(szFullPath->c_str());
|
||||
case ArchiveLocationPriority::ePakPriorityPakOnly:
|
||||
case FileSearchPriority::PakOnly:
|
||||
return FindPakFileEntry(szFullPath->Native());
|
||||
default:
|
||||
AZ_Assert(false, "PakPriority %d doesn't match a value in the ArchiveLocationPriority enum",
|
||||
AZ_Assert(false, "PakPriority %d doesn't match a value in the FileSearchPriority enum",
|
||||
aznumeric_cast<int>(nVarPakPriority));
|
||||
}
|
||||
break;
|
||||
case IArchive::eFileLocation_InPak:
|
||||
case FileSearchLocation::InPak:
|
||||
return FindPakFileEntry(szFullPath->Native());
|
||||
case IArchive::eFileLocation_OnDisk:
|
||||
if (nVarPakPriority != ArchiveLocationPriority::ePakPriorityPakOnly)
|
||||
case FileSearchLocation::OnDisk:
|
||||
if (nVarPakPriority != FileSearchPriority::PakOnly)
|
||||
{
|
||||
return FileIOBase::GetDirectInstance()->Exists(szFullPath->c_str());
|
||||
}
|
||||
@@ -485,7 +486,7 @@ namespace AZ::IO
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool Archive::IsFolder(AZStd::string_view sPath)
|
||||
{
|
||||
AZStd::fixed_string<AZ::IO::MaxPathLength > filePath{ sPath };
|
||||
AZ::IO::FixedMaxPath filePath{ sPath };
|
||||
return AZ::IO::FileIOBase::GetDirectInstance()->IsDirectory(filePath.c_str());
|
||||
}
|
||||
|
||||
@@ -515,7 +516,7 @@ namespace AZ::IO
|
||||
|
||||
// get the priority into local variable to avoid it changing in the course of
|
||||
// this function execution (?)
|
||||
const ArchiveLocationPriority nVarPakPriority = GetPakPriority();
|
||||
const FileSearchPriority nVarPakPriority = GetPakPriority();
|
||||
|
||||
AZ::IO::OpenMode nOSFlags = AZ::IO::GetOpenModeFromStringMode(szMode);
|
||||
|
||||
@@ -628,17 +629,17 @@ namespace AZ::IO
|
||||
|
||||
switch (nVarPakPriority)
|
||||
{
|
||||
case ArchiveLocationPriority::ePakPriorityFileFirst:
|
||||
case FileSearchPriority::FileFirst:
|
||||
{
|
||||
AZ::IO::HandleType fileHandle = OpenFromFileSystem();
|
||||
return fileHandle != AZ::IO::InvalidHandle ? fileHandle : OpenFromArchive();
|
||||
}
|
||||
case ArchiveLocationPriority::ePakPriorityPakFirst:
|
||||
case FileSearchPriority::PakFirst:
|
||||
{
|
||||
AZ::IO::HandleType fileHandle = OpenFromArchive();
|
||||
return fileHandle != AZ::IO::InvalidHandle ? fileHandle : OpenFromFileSystem();
|
||||
}
|
||||
case ArchiveLocationPriority::ePakPriorityPakOnly:
|
||||
case FileSearchPriority::PakOnly:
|
||||
{
|
||||
return OpenFromArchive();
|
||||
}
|
||||
@@ -810,7 +811,7 @@ namespace AZ::IO
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (GetPakPriority() == ArchiveLocationPriority::ePakPriorityFileFirst) // if the file system files have priority now..
|
||||
if (GetPakPriority() == FileSearchPriority::FileFirst) // if the file system files have priority now..
|
||||
{
|
||||
IArchive::SignedFileSize nFileSize = GetFileSizeOnDisk(fullPath->Native());
|
||||
if (nFileSize != IArchive::FILE_NOT_PRESENT)
|
||||
@@ -825,7 +826,7 @@ namespace AZ::IO
|
||||
return pFileEntry->desc.lSizeUncompressed;
|
||||
}
|
||||
|
||||
if (bAllowUseFileSystem || GetPakPriority() == ArchiveLocationPriority::ePakPriorityPakFirst) // if the archive files had more priority, we didn't attempt fopen before- try it now
|
||||
if (bAllowUseFileSystem || GetPakPriority() == FileSearchPriority::PakFirst) // if the archive files had more priority, we didn't attempt fopen before- try it now
|
||||
{
|
||||
IArchive::SignedFileSize nFileSize = GetFileSizeOnDisk(fullPath->Native());
|
||||
if (nFileSize != IArchive::FILE_NOT_PRESENT)
|
||||
@@ -1023,7 +1024,7 @@ namespace AZ::IO
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
AZ::IO::ArchiveFileIterator Archive::FindFirst(AZStd::string_view pDir, EFileSearchType searchType)
|
||||
AZ::IO::ArchiveFileIterator Archive::FindFirst(AZStd::string_view pDir, FileSearchLocation searchType)
|
||||
{
|
||||
auto szFullPath = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pDir);
|
||||
if (!szFullPath)
|
||||
@@ -1036,18 +1037,21 @@ namespace AZ::IO
|
||||
bool bAllowUseFileSystem{};
|
||||
switch (searchType)
|
||||
{
|
||||
case IArchive::eFileSearchType_AllowInZipsOnly:
|
||||
bAllowUseFileSystem = false;
|
||||
bScanZips = true;
|
||||
break;
|
||||
case IArchive::eFileSearchType_AllowOnDiskAndInZips:
|
||||
bAllowUseFileSystem = true;
|
||||
bScanZips = true;
|
||||
break;
|
||||
case IArchive::eFileSearchType_AllowOnDiskOnly:
|
||||
bAllowUseFileSystem = true;
|
||||
bScanZips = false;
|
||||
break;
|
||||
case FileSearchLocation::InPak:
|
||||
bAllowUseFileSystem = false;
|
||||
bScanZips = true;
|
||||
break;
|
||||
case FileSearchLocation::Any:
|
||||
bAllowUseFileSystem = true;
|
||||
bScanZips = true;
|
||||
break;
|
||||
case FileSearchLocation::OnDisk:
|
||||
bAllowUseFileSystem = true;
|
||||
bScanZips = false;
|
||||
break;
|
||||
default:
|
||||
AZ_Assert(false, "Invalid search location value supplied");
|
||||
break;
|
||||
}
|
||||
|
||||
AZStd::intrusive_ptr pFindData = aznew AZ::IO::FindData();
|
||||
@@ -1218,7 +1222,7 @@ namespace AZ::IO
|
||||
else
|
||||
{
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
AZStd::vector<AZStd::string> levelDirs;
|
||||
AZStd::vector<AZ::IO::Path> levelDirs;
|
||||
|
||||
if (addLevels)
|
||||
{
|
||||
@@ -1380,7 +1384,7 @@ namespace AZ::IO
|
||||
return true;
|
||||
}
|
||||
|
||||
if (AZ::IO::ArchiveFileIterator fileIterator = FindFirst(pWildcardIn, IArchive::eFileSearchType_AllowOnDiskOnly); fileIterator)
|
||||
if (AZ::IO::ArchiveFileIterator fileIterator = FindFirst(pWildcardIn, FileSearchLocation::OnDisk); fileIterator)
|
||||
{
|
||||
AZStd::vector<AZ::IO::FixedMaxPath> files;
|
||||
do
|
||||
@@ -1955,15 +1959,15 @@ namespace AZ::IO
|
||||
}
|
||||
|
||||
// gets the current archive priority
|
||||
ArchiveLocationPriority Archive::GetPakPriority() const
|
||||
FileSearchPriority Archive::GetPakPriority() const
|
||||
{
|
||||
int pakPriority = aznumeric_cast<int>(ArchiveVars{}.nPriority);
|
||||
FileSearchPriority pakPriority = ArchiveVars{}.m_fileSearchPriority;
|
||||
if (auto console = AZ::Interface<AZ::IConsole>::Get(); console != nullptr)
|
||||
{
|
||||
[[maybe_unused]] AZ::GetValueResult getCvarResult = console->GetCvarValue("sys_PakPriority", pakPriority);
|
||||
[[maybe_unused]] AZ::GetValueResult getCvarResult = console->GetCvarValue("sys_PakPriority", reinterpret_cast<int&>(pakPriority));
|
||||
AZ_Error("Archive", getCvarResult == AZ::GetValueResult::Success, "Lookup of 'sys_PakPriority console variable failed with error %s", AZ::GetEnumString(getCvarResult));
|
||||
}
|
||||
return static_cast<ArchiveLocationPriority>(pakPriority);
|
||||
return pakPriority;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -2030,13 +2034,13 @@ namespace AZ::IO
|
||||
|
||||
switch (GetPakPriority())
|
||||
{
|
||||
case ArchiveLocationPriority::ePakPriorityFileFirst:
|
||||
case FileSearchPriority::FileFirst:
|
||||
info.m_conflictResolution = AZ::IO::ConflictResolution::PreferFile;
|
||||
break;
|
||||
case ArchiveLocationPriority::ePakPriorityPakFirst:
|
||||
case FileSearchPriority::PakFirst:
|
||||
info.m_conflictResolution = AZ::IO::ConflictResolution::PreferArchive;
|
||||
break;
|
||||
case ArchiveLocationPriority::ePakPriorityPakOnly:
|
||||
case FileSearchPriority::PakOnly:
|
||||
info.m_conflictResolution = AZ::IO::ConflictResolution::UseArchiveOnly;
|
||||
break;
|
||||
}
|
||||
@@ -2147,13 +2151,13 @@ namespace AZ::IO
|
||||
return manifestInfo;
|
||||
}
|
||||
|
||||
AZStd::vector<AZStd::string> Archive::ScanForLevels(ZipDir::CachePtr pZip)
|
||||
AZStd::vector<AZ::IO::Path> Archive::ScanForLevels(ZipDir::CachePtr pZip)
|
||||
{
|
||||
AZStd::queue<AZStd::string> scanDirs;
|
||||
AZStd::vector<AZStd::string> levelDirs;
|
||||
AZStd::string currentDir = "levels";
|
||||
AZStd::string currentDirPattern;
|
||||
AZStd::string currentFilePattern;
|
||||
AZStd::queue<AZ::IO::Path> scanDirs;
|
||||
AZStd::vector<AZ::IO::Path> levelDirs;
|
||||
AZ::IO::Path currentDir = "levels";
|
||||
AZ::IO::Path currentDirPattern;
|
||||
AZ::IO::Path currentFilePattern;
|
||||
ZipDir::FindDir findDir(pZip);
|
||||
|
||||
findDir.FindFirst(currentDir.c_str());
|
||||
@@ -2171,11 +2175,10 @@ namespace AZ::IO
|
||||
scanDirs.pop();
|
||||
}
|
||||
|
||||
currentDirPattern = currentDir + AZ_FILESYSTEM_SEPARATOR_WILDCARD;
|
||||
currentFilePattern = currentDir + AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING + "level.pak";
|
||||
currentDirPattern = currentDir / "*";
|
||||
currentFilePattern = currentDir / "level.pak";
|
||||
|
||||
ZipDir::FileEntry* fileEntry = findFile.FindExact(currentFilePattern.c_str());
|
||||
if (fileEntry)
|
||||
if (ZipDir::FileEntry* fileEntry = findFile.FindExact(currentFilePattern); fileEntry)
|
||||
{
|
||||
levelDirs.emplace_back(currentDir);
|
||||
continue;
|
||||
@@ -2183,9 +2186,7 @@ namespace AZ::IO
|
||||
|
||||
for (findDir.FindFirst(currentDirPattern.c_str()); findDir.GetDirEntry(); findDir.FindNext())
|
||||
{
|
||||
AZStd::string_view dirName = findDir.GetDirName();
|
||||
AZStd::string dirToAdd = AZStd::string::format("%s/%.*s", currentDir.data(), aznumeric_cast<int>(dirName.size()), dirName.data());
|
||||
scanDirs.push(dirToAdd);
|
||||
scanDirs.push(currentDir / findDir.GetDirName());
|
||||
}
|
||||
} while (!scanDirs.empty());
|
||||
|
||||
|
||||
@@ -207,7 +207,7 @@ namespace AZ::IO
|
||||
uint64_t FTell(AZ::IO::HandleType handle) override;
|
||||
int FFlush(AZ::IO::HandleType handle) override;
|
||||
int FClose(AZ::IO::HandleType handle) override;
|
||||
AZ::IO::ArchiveFileIterator FindFirst(AZStd::string_view pDir, EFileSearchType searchType = eFileSearchType_AllowInZipsOnly) override;
|
||||
AZ::IO::ArchiveFileIterator FindFirst(AZStd::string_view pDir, FileSearchLocation searchType = FileSearchLocation::InPak) override;
|
||||
AZ::IO::ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator fileIterator) override;
|
||||
bool FindClose(AZ::IO::ArchiveFileIterator fileIterator) override;
|
||||
int FEof(AZ::IO::HandleType handle) override;
|
||||
@@ -219,7 +219,7 @@ namespace AZ::IO
|
||||
bool RemoveDir(AZStd::string_view pName) override; // remove directory from FS (if supported)
|
||||
bool IsAbsPath(AZStd::string_view pPath) override;
|
||||
|
||||
bool IsFileExist(AZStd::string_view sFilename, EFileSearchLocation fileLocation = eFileLocation_Any) override;
|
||||
bool IsFileExist(AZStd::string_view sFilename, FileSearchLocation fileLocation = FileSearchLocation::Any) override;
|
||||
bool IsFolder(AZStd::string_view sPath) override;
|
||||
IArchive::SignedFileSize GetFileSizeOnDisk(AZStd::string_view filename) override;
|
||||
|
||||
@@ -255,7 +255,7 @@ namespace AZ::IO
|
||||
bool DisableRuntimeFileAccess(bool status, AZStd::thread_id threadId) override;
|
||||
|
||||
// gets the current archive priority
|
||||
ArchiveLocationPriority GetPakPriority() const override;
|
||||
FileSearchPriority GetPakPriority() const override;
|
||||
|
||||
uint64_t GetFileOffsetOnMedia(AZStd::string_view szName) const override;
|
||||
|
||||
@@ -305,7 +305,7 @@ namespace AZ::IO
|
||||
AZStd::shared_ptr<AzFramework::AssetRegistry> GetBundleCatalog(ZipDir::CachePtr pZip, const AZStd::string& catalogName);
|
||||
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
AZStd::vector<AZStd::string> ScanForLevels(ZipDir::CachePtr pZip);
|
||||
AZStd::vector<AZ::IO::Path> ScanForLevels(ZipDir::CachePtr pZip);
|
||||
|
||||
mutable AZStd::shared_mutex m_csOpenFiles;
|
||||
ZipPseudoFileArray m_arrOpenFiles;
|
||||
|
||||
@@ -169,7 +169,7 @@ namespace AZ::IO
|
||||
size = m_archive->FGetSize(filePath, true);
|
||||
if (!size)
|
||||
{
|
||||
return m_archive->IsFileExist(filePath, IArchive::eFileLocation_Any) ? IO::ResultCode::Success : IO::ResultCode::Error;
|
||||
return m_archive->IsFileExist(filePath, FileSearchLocation::Any) ? IO::ResultCode::Success : IO::ResultCode::Error;
|
||||
}
|
||||
|
||||
return IO::ResultCode::Success;
|
||||
|
||||
@@ -78,9 +78,9 @@ namespace AZ::IO
|
||||
{
|
||||
// get the priority into local variable to avoid it changing in the course of
|
||||
// this function execution
|
||||
ArchiveLocationPriority nVarPakPriority = archive->GetPakPriority();
|
||||
FileSearchPriority nVarPakPriority = archive->GetPakPriority();
|
||||
|
||||
if (nVarPakPriority == ArchiveLocationPriority::ePakPriorityFileFirst)
|
||||
if (nVarPakPriority == FileSearchPriority::FileFirst)
|
||||
{
|
||||
// first, find the file system files
|
||||
ScanFS(archive, szDir);
|
||||
@@ -96,7 +96,7 @@ namespace AZ::IO
|
||||
{
|
||||
ScanZips(archive, szDir);
|
||||
}
|
||||
if (bAllowUseFS || nVarPakPriority != ArchiveLocationPriority::ePakPriorityPakOnly)
|
||||
if (bAllowUseFS || nVarPakPriority != FileSearchPriority::PakOnly)
|
||||
{
|
||||
ScanFS(archive, szDir);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <AzFramework/Archive/ArchiveVars.h>
|
||||
|
||||
namespace AZ::IO
|
||||
{
|
||||
FileSearchPriority GetDefaultFileSearchPriority()
|
||||
{
|
||||
#if defined(LY_ARCHIVE_FILE_SEARCH_MODE_DEFAULT)
|
||||
return FileSearchPriority{ LY_ARCHIVE_FILE_SEARCH_MODE_DEFAULT };
|
||||
#else
|
||||
return FileSearchPriority{};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,24 @@
|
||||
|
||||
namespace AZ::IO
|
||||
{
|
||||
enum class ArchiveLocationPriority
|
||||
enum class FileSearchPriority
|
||||
{
|
||||
ePakPriorityFileFirst = 0,
|
||||
ePakPriorityPakFirst = 1,
|
||||
ePakPriorityPakOnly = 2
|
||||
FileFirst,
|
||||
PakFirst,
|
||||
PakOnly
|
||||
};
|
||||
|
||||
|
||||
//file location enum used in isFileExist to control where the archive system looks for the file.
|
||||
enum class FileSearchLocation
|
||||
{
|
||||
Any,
|
||||
OnDisk,
|
||||
InPak
|
||||
};
|
||||
|
||||
FileSearchPriority GetDefaultFileSearchPriority();
|
||||
|
||||
// variables that control behavior of the Archive subsystem
|
||||
struct ArchiveVars
|
||||
{
|
||||
@@ -28,8 +39,6 @@ namespace AZ::IO
|
||||
#else
|
||||
inline static constexpr bool IsReleaseConfig{};
|
||||
#endif
|
||||
|
||||
public:
|
||||
int nReadSlice{};
|
||||
int nSaveTotalResourceList{};
|
||||
int nSaveFastloadResourceList{};
|
||||
@@ -42,9 +51,7 @@ namespace AZ::IO
|
||||
int nLoadCache{};
|
||||
int nLoadModePaks{};
|
||||
int nStreamCache{ STREAM_CACHE_DEFAULT };
|
||||
ArchiveLocationPriority nPriority{ IsReleaseConfig
|
||||
? ArchiveLocationPriority::ePakPriorityPakOnly
|
||||
: ArchiveLocationPriority::ePakPriorityFileFirst }; // Which file location to favor (loose vs. pak files)
|
||||
FileSearchPriority m_fileSearchPriority{ GetDefaultFileSearchPriority()};
|
||||
int nMessageInvalidFileAccess{};
|
||||
int nLogInvalidFileAccess{ IsReleaseConfig ? 0 : 1 };
|
||||
int nDisableNonLevelRelatedPaks{ 1 };
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
#include <AzCore/std/string/fixed_string.h>
|
||||
|
||||
#include <AzFramework/Archive/ArchiveFindData.h>
|
||||
|
||||
#include <AzFramework/Archive/ArchiveVars.h>
|
||||
|
||||
enum EStreamSourceMediaType : int32_t;
|
||||
|
||||
namespace AZ::IO
|
||||
{
|
||||
enum class ArchiveLocationPriority;
|
||||
enum class FileSearchPriority;
|
||||
struct IResourceList;
|
||||
struct INestedArchive;
|
||||
struct IArchive;
|
||||
@@ -114,14 +114,6 @@ namespace AZ::IO
|
||||
RFOM_NextLevel // used for level2level loading
|
||||
};
|
||||
|
||||
//file location enum used in isFileExist to control where the archive system looks for the file.
|
||||
enum EFileSearchLocation
|
||||
{
|
||||
eFileLocation_Any = 0,
|
||||
eFileLocation_OnDisk,
|
||||
eFileLocation_InPak,
|
||||
};
|
||||
|
||||
enum EInMemoryArchiveLocation
|
||||
{
|
||||
eInMemoryPakLocale_Unload = 0,
|
||||
@@ -130,12 +122,6 @@ namespace AZ::IO
|
||||
eInMemoryPakLocale_PAK,
|
||||
};
|
||||
|
||||
enum EFileSearchType
|
||||
{
|
||||
eFileSearchType_AllowInZipsOnly = 0,
|
||||
eFileSearchType_AllowOnDiskAndInZips,
|
||||
eFileSearchType_AllowOnDiskOnly
|
||||
};
|
||||
|
||||
using SignedFileSize = int64_t;
|
||||
|
||||
@@ -213,7 +199,7 @@ namespace AZ::IO
|
||||
virtual AZStd::intrusive_ptr<AZ::IO::MemoryBlock> PoolAllocMemoryBlock(size_t nSize, const char* sUsage, size_t nAlign = 1) = 0;
|
||||
|
||||
// Arguments:
|
||||
virtual ArchiveFileIterator FindFirst(AZStd::string_view pDir, EFileSearchType searchType = eFileSearchType_AllowInZipsOnly) = 0;
|
||||
virtual ArchiveFileIterator FindFirst(AZStd::string_view pDir, FileSearchLocation searchType = FileSearchLocation::InPak) = 0;
|
||||
virtual ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator handle) = 0;
|
||||
virtual bool FindClose(AZ::IO::ArchiveFileIterator handle) = 0;
|
||||
//returns file modification time
|
||||
@@ -221,7 +207,7 @@ namespace AZ::IO
|
||||
|
||||
// Description:
|
||||
// Checks if specified file exist in filesystem.
|
||||
virtual bool IsFileExist(AZStd::string_view sFilename, EFileSearchLocation = eFileLocation_Any) = 0;
|
||||
virtual bool IsFileExist(AZStd::string_view sFilename, FileSearchLocation = FileSearchLocation::Any) = 0;
|
||||
|
||||
// Checks if path is a folder
|
||||
virtual bool IsFolder(AZStd::string_view sPath) = 0;
|
||||
@@ -283,7 +269,7 @@ namespace AZ::IO
|
||||
virtual bool DisableRuntimeFileAccess(bool status, AZStd::thread_id threadId) = 0;
|
||||
|
||||
// gets the current pak priority
|
||||
virtual ArchiveLocationPriority GetPakPriority() const = 0;
|
||||
virtual FileSearchPriority GetPakPriority() const = 0;
|
||||
|
||||
// Summary:
|
||||
// Return offset in archive file (ideally has to return offset on DVD) for streaming requests sorting
|
||||
@@ -295,7 +281,7 @@ namespace AZ::IO
|
||||
|
||||
// Event sent when a archive file is opened that contains a level.pak
|
||||
// @param const AZStd::vector<AZStd::string>& - Array of directories containing level.pak files
|
||||
using LevelPackOpenEvent = AZ::Event<const AZStd::vector<AZStd::string>&>;
|
||||
using LevelPackOpenEvent = AZ::Event<const AZStd::vector<AZ::IO::Path>&>;
|
||||
virtual auto GetLevelPackOpenEvent()->LevelPackOpenEvent* = 0;
|
||||
// Event sent when a archive contains a level.pak is closed
|
||||
// @param const AZStd::string_view - Name of the pak file that was closed
|
||||
|
||||
@@ -7,23 +7,153 @@
|
||||
*/
|
||||
|
||||
#include <AzFramework/Asset/AssetBundleManifest.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Serialization/ObjectStream.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
|
||||
const int AssetBundleManifest::CurrentBundleVersion = 2;
|
||||
// Redirects writing of the AssetBundleManifest to an older version if the bundle version
|
||||
// is not set to the current version
|
||||
static void OldBundleManifestWriter(AZ::SerializeContext::EnumerateInstanceCallContext& callContext, const void* bundleManifestPointer,
|
||||
const AZ::SerializeContext::ClassData&, const AZ::SerializeContext::ClassElement* assetBundleManifestClassElement);
|
||||
|
||||
static bool BundleManifestVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& rootElement);
|
||||
|
||||
const int AssetBundleManifest::CurrentBundleVersion = 3;
|
||||
const char AssetBundleManifest::s_manifestFileName[] = "manifest.xml";
|
||||
|
||||
AssetBundleManifest::AssetBundleManifest() = default;
|
||||
AssetBundleManifest::~AssetBundleManifest() = default;
|
||||
|
||||
void AssetBundleManifest::ReflectSerialize(AZ::SerializeContext* serializeContext)
|
||||
{
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AssetBundleManifest>()
|
||||
->Version(2)
|
||||
->Version(CurrentBundleVersion, &BundleManifestVersionConverter)
|
||||
->Attribute(AZ::SerializeContextAttributes::ObjectStreamWriteElementOverride, &OldBundleManifestWriter)
|
||||
->Field("BundleVersion", &AssetBundleManifest::m_bundleVersion)
|
||||
->Field("CatalogName", &AssetBundleManifest::m_catalogName)
|
||||
->Field("DependentBundleNames", &AssetBundleManifest::m_depedendentBundleNames)
|
||||
->Field("DependentBundleNames", &AssetBundleManifest::m_dependentBundleNames)
|
||||
->Field("LevelNames", &AssetBundleManifest::m_levelDirs);
|
||||
|
||||
// Make sure the AZStd::vector<AZStd::string> type is reflected so that it can be read
|
||||
// using DataElement::GetChildData
|
||||
serializeContext->RegisterGenericType<AZStd::vector<AZStd::string>>();
|
||||
}
|
||||
}
|
||||
|
||||
bool BundleManifestVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& rootElement)
|
||||
{
|
||||
if (rootElement.GetVersion() < 3)
|
||||
{
|
||||
static constexpr AZ::u32 levelNamesCrc = AZ_CRC_CE("LevelNames");
|
||||
AZStd::vector<AZ::IO::Path> newLevelDirs;
|
||||
if (AZStd::vector<AZStd::string> oldLevelNames; rootElement.GetChildData(levelNamesCrc, oldLevelNames))
|
||||
{
|
||||
newLevelDirs.insert(newLevelDirs.end(),
|
||||
AZStd::make_move_iterator(oldLevelNames.begin()), AZStd::make_move_iterator(oldLevelNames.end()));
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("AssetBundleManifest", false, R"(Unable to read "levelNames" from AssetBundleManifest version %u )",
|
||||
rootElement.GetVersion());
|
||||
}
|
||||
|
||||
rootElement.RemoveElementByName(levelNamesCrc);
|
||||
rootElement.AddElementWithData(context, "LevelNames", newLevelDirs);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void OldBundleManifestWriter(AZ::SerializeContext::EnumerateInstanceCallContext& callContext, const void* bundleManifestPointer,
|
||||
const AZ::SerializeContext::ClassData&, const AZ::SerializeContext::ClassElement* assetBundleManifestClassElement)
|
||||
{
|
||||
// Copy the AssetBundleManifest current version instance to the AssetBundleManifest V2 instance
|
||||
auto assetBundleManifestCurrent = reinterpret_cast<const AssetBundleManifest*>(bundleManifestPointer);
|
||||
if (assetBundleManifestCurrent->GetBundleVersion() <= 2)
|
||||
{
|
||||
auto serializeContext = const_cast<AZ::SerializeContext*>(callContext.m_context);
|
||||
|
||||
struct AssetBundleManifestV2
|
||||
{
|
||||
// Use the same ClassName and typeid as the AssetBundleManifest
|
||||
AZ_TYPE_INFO(AssetBundleManifest, azrtti_typeid<AssetBundleManifest>());
|
||||
AZStd::string m_catalogName;
|
||||
AZStd::vector<AZStd::string> m_dependentBundleNames;
|
||||
AZStd::vector<AZStd::string> m_levelDirs;
|
||||
int m_bundleVersion{};
|
||||
};
|
||||
auto ReflectAssetBundleManifestV2 = [](AZ::SerializeContext* serializeContext)
|
||||
{
|
||||
serializeContext->Class<AssetBundleManifestV2>()
|
||||
->Version(2)
|
||||
->Field("BundleVersion", &AssetBundleManifestV2::m_bundleVersion)
|
||||
->Field("CatalogName", &AssetBundleManifestV2::m_catalogName)
|
||||
->Field("DependentBundleNames", &AssetBundleManifestV2::m_dependentBundleNames)
|
||||
->Field("LevelNames", &AssetBundleManifestV2::m_levelDirs);
|
||||
};
|
||||
|
||||
// Unreflect the AssetBundleManifest class at the version since it shares the same typeid
|
||||
// as the older version and Reflect the V2 AssetBundlerManifest
|
||||
serializeContext->EnableRemoveReflection();
|
||||
AssetBundleManifest::ReflectSerialize(serializeContext);
|
||||
serializeContext->DisableRemoveReflection();
|
||||
ReflectAssetBundleManifestV2(serializeContext);
|
||||
|
||||
// Use the Current AssetBundleManifest instance to make a Version 2 AssetBundleManifest
|
||||
AssetBundleManifestV2 assetBundleManifestV2;
|
||||
assetBundleManifestV2.m_catalogName = assetBundleManifestCurrent->GetCatalogName();
|
||||
assetBundleManifestV2.m_dependentBundleNames = assetBundleManifestCurrent->GetDependentBundleNames();
|
||||
assetBundleManifestV2.m_bundleVersion = assetBundleManifestCurrent->GetBundleVersion();
|
||||
for (const AZ::IO::Path& levelDir : assetBundleManifestCurrent->GetLevelDirectories())
|
||||
{
|
||||
assetBundleManifestV2.m_levelDirs.emplace_back(levelDir.Native());
|
||||
}
|
||||
|
||||
const AZ::TypeId& assetBundlerManifestTypeId = azrtti_typeid<AssetBundleManifestV2>();
|
||||
const auto assetBundleManifestV2ClassData = serializeContext->FindClassData(assetBundlerManifestTypeId);
|
||||
|
||||
// Create an AssetBundleManifest Version 2 Class Eleemnt
|
||||
// It will copy over the name and nameCrc values of the current AssetBundleManifestelemnt
|
||||
auto CreateAssetBundleManifestV2ClassElement = [&assetBundlerManifestTypeId](
|
||||
const AZ::SerializeContext::ClassElement* currentVersionElement) -> AZ::SerializeContext::ClassElement
|
||||
{
|
||||
AZ::SerializeContext::ClassElement v2ClassElement;
|
||||
// Copy over the name of he current
|
||||
if (currentVersionElement)
|
||||
{
|
||||
v2ClassElement.m_name = currentVersionElement->m_name;
|
||||
v2ClassElement.m_nameCrc = currentVersionElement->m_nameCrc;
|
||||
}
|
||||
v2ClassElement.m_dataSize = sizeof(AssetBundleManifest);
|
||||
v2ClassElement.m_azRtti = AZ::GetRttiHelper<AssetBundleManifestV2>();
|
||||
v2ClassElement.m_genericClassInfo = nullptr;
|
||||
v2ClassElement.m_typeId = assetBundlerManifestTypeId;
|
||||
v2ClassElement.m_editData = nullptr;
|
||||
v2ClassElement.m_attributeOwnership = AZ::SerializeContext::ClassElement::AttributeOwnership::Self;
|
||||
return v2ClassElement;
|
||||
};
|
||||
const auto assetBundleManifestV2ClassElement = CreateAssetBundleManifestV2ClassElement(assetBundleManifestClassElement);
|
||||
|
||||
serializeContext->EnumerateInstanceConst(&callContext, &assetBundleManifestV2, assetBundlerManifestTypeId,
|
||||
assetBundleManifestV2ClassData, assetBundleManifestClassElement ? &assetBundleManifestV2ClassElement : nullptr);
|
||||
|
||||
// Unreflect the V2 AssetBundleManifest and Re-reflect the AssetBundleManifest class at the current version
|
||||
serializeContext->EnableRemoveReflection();
|
||||
ReflectAssetBundleManifestV2(serializeContext);
|
||||
serializeContext->DisableRemoveReflection();
|
||||
AssetBundleManifest::ReflectSerialize(serializeContext);
|
||||
}
|
||||
}
|
||||
|
||||
const AZStd::vector<AZ::IO::Path>& AssetBundleManifest::GetLevelDirectories() const
|
||||
{
|
||||
return m_levelDirs;
|
||||
}
|
||||
void AssetBundleManifest::SetLevelsDirectory(const AZStd::vector<AZ::IO::Path>& levelDirs)
|
||||
{
|
||||
m_levelDirs = levelDirs;
|
||||
}
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/IO/Path/Path_fwd.h>
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
@@ -27,7 +28,8 @@ namespace AzFramework
|
||||
AZ_TYPE_INFO(AssetBundleManifest, "{8628A669-7B19-4C48-A7CB-F670CC9586FD}");
|
||||
AZ_CLASS_ALLOCATOR(AssetBundleManifest, AZ::SystemAllocator, 0);
|
||||
|
||||
AssetBundleManifest() = default;
|
||||
AssetBundleManifest();
|
||||
~AssetBundleManifest();
|
||||
|
||||
static void ReflectSerialize(AZ::SerializeContext* serializeContext);
|
||||
|
||||
@@ -35,21 +37,21 @@ namespace AzFramework
|
||||
// of files within the AssetBundle in order to update the Asset Registry at runtime when
|
||||
// loading the bundle
|
||||
const AZStd::string& GetCatalogName() const { return m_catalogName; }
|
||||
AZStd::vector<AZStd::string> GetDependentBundleNames() const { return m_depedendentBundleNames; }
|
||||
AZStd::vector<AZStd::string> GetLevelDirectories() const { return m_levelDirs; }
|
||||
AZStd::vector<AZStd::string> GetDependentBundleNames() const { return m_dependentBundleNames; }
|
||||
const AZStd::vector<AZ::IO::Path>& GetLevelDirectories() const;
|
||||
int GetBundleVersion() const { return m_bundleVersion; }
|
||||
void SetCatalogName(const AZStd::string& catalogName) { m_catalogName = catalogName; }
|
||||
void SetBundleVersion(int bundleVersion) { m_bundleVersion = bundleVersion; }
|
||||
void SetDependentBundleNames(const AZStd::vector<AZStd::string>& dependentBundleNames) { m_depedendentBundleNames = dependentBundleNames; }
|
||||
void SetLevelsDirectory(const AZStd::vector<AZStd::string>& levelDirs) { m_levelDirs = levelDirs; }
|
||||
void SetDependentBundleNames(const AZStd::vector<AZStd::string>& dependentBundleNames) { m_dependentBundleNames = dependentBundleNames; }
|
||||
void SetLevelsDirectory(const AZStd::vector<AZ::IO::Path>& levelDirs);
|
||||
|
||||
static const char s_manifestFileName[];
|
||||
static const int CurrentBundleVersion;
|
||||
|
||||
private:
|
||||
private:
|
||||
AZStd::string m_catalogName;
|
||||
AZStd::vector<AZStd::string> m_depedendentBundleNames;
|
||||
AZStd::vector<AZStd::string> m_levelDirs;
|
||||
AZStd::vector<AZStd::string> m_dependentBundleNames;
|
||||
AZStd::vector<AZ::IO::Path> m_levelDirs;
|
||||
int m_bundleVersion = CurrentBundleVersion;
|
||||
};
|
||||
|
||||
|
||||
@@ -1186,7 +1186,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
|
||||
bool AssetCatalog::CreateBundleManifest(const AZStd::string& deltaCatalogPath, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& fileDirectory, int bundleVersion, const AZStd::vector<AZStd::string>& levelDirs)
|
||||
bool AssetCatalog::CreateBundleManifest(const AZStd::string& deltaCatalogPath, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& fileDirectory, int bundleVersion, const AZStd::vector<AZ::IO::Path>& levelDirs)
|
||||
{
|
||||
if (bundleVersion > AzFramework::AssetBundleManifest::CurrentBundleVersion || bundleVersion < 0)
|
||||
{
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace AzFramework
|
||||
bool InsertDeltaCatalogBefore(AZStd::shared_ptr<AzFramework::AssetRegistry> deltaCatalog, AZStd::shared_ptr<AzFramework::AssetRegistry> afterDeltaCatalog) override;
|
||||
bool RemoveDeltaCatalog(AZStd::shared_ptr<AzFramework::AssetRegistry> deltaCatalog) override;
|
||||
static bool SaveAssetBundleManifest(const char* assetBundleManifestFile, AzFramework::AssetBundleManifest* bundleManifest);
|
||||
bool CreateBundleManifest(const AZStd::string& deltaCatalogPath, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& fileDirectory, int bundleVersion, const AZStd::vector<AZStd::string>& levelDirs) override;
|
||||
bool CreateBundleManifest(const AZStd::string& deltaCatalogPath, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& fileDirectory, int bundleVersion, const AZStd::vector<AZ::IO::Path>& levelDirs) override;
|
||||
bool CreateDeltaCatalog(const AZStd::vector<AZStd::string>& files, const AZStd::string& filePath) override;
|
||||
void AddExtension(const char* extension) override;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ set(FILES
|
||||
Archive/ArchiveFindData.cpp
|
||||
Archive/ArchiveFindData.h
|
||||
Archive/ArchiveVars.h
|
||||
Archive/ArchiveVars.cpp
|
||||
Archive/Codec.h
|
||||
Archive/IArchive.h
|
||||
Archive/INestedArchive.h
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
|
||||
ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common)
|
||||
|
||||
@@ -33,6 +32,14 @@ ly_add_target(
|
||||
3rdParty::lz4
|
||||
)
|
||||
|
||||
set(LY_SEARCH_MODE_DEFINE $<$<NOT:$<STREQUAL:"${LY_ARCHIVE_FILE_SEARCH_MODE}","">>:LY_ARCHIVE_FILE_SEARCH_MODE_DEFAULT=${LY_ARCHIVE_FILE_SEARCH_MODE}>)
|
||||
|
||||
ly_add_source_properties(
|
||||
SOURCES
|
||||
AzFramework/Archive/ArchiveVars.cpp
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
VALUES ${LY_SEARCH_MODE_DEFINE})
|
||||
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
|
||||
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Tests/Platform/${PAL_PLATFORM_NAME})
|
||||
|
||||
@@ -273,7 +273,7 @@ namespace UnitTest
|
||||
// Also enable extra verbosity in the AZ::IO::Archive code
|
||||
CVarIntValueScope previousLocationPriority{ *console, "sys_pakPriority" };
|
||||
CVarIntValueScope oldArchiveVerbosity{ *console, "az_archive_verbosity" };
|
||||
console->PerformCommand("sys_PakPriority", { AZ::CVarFixedString::format("%d", aznumeric_cast<int>(AZ::IO::ArchiveLocationPriority::ePakPriorityPakOnly)) });
|
||||
console->PerformCommand("sys_PakPriority", { AZ::CVarFixedString::format("%d", aznumeric_cast<int>(AZ::IO::FileSearchPriority::PakOnly)) });
|
||||
console->PerformCommand("az_archive_verbosity", { "1" });
|
||||
|
||||
// ---- Archive FGetCachedFileDataTests (these leverage Archive CachedFile mechanism for caching data ---
|
||||
@@ -459,7 +459,7 @@ namespace UnitTest
|
||||
|
||||
// Once the archive has been deleted it should no longer be searched
|
||||
CVarIntValueScope previousLocationPriority{ *console, "sys_pakPriority" };
|
||||
console->PerformCommand("sys_PakPriority", { AZ::CVarFixedString::format("%d", aznumeric_cast<int>(AZ::IO::ArchiveLocationPriority::ePakPriorityPakOnly)) });
|
||||
console->PerformCommand("sys_PakPriority", { AZ::CVarFixedString::format("%d", aznumeric_cast<int>(AZ::IO::FileSearchPriority::PakOnly)) });
|
||||
|
||||
handle = archive->FindFirst("levels\\*");
|
||||
EXPECT_FALSE(static_cast<bool>(handle));
|
||||
@@ -785,7 +785,7 @@ namespace UnitTest
|
||||
|
||||
EXPECT_TRUE(archive->OpenPack("@usercache@", realNameBuf));
|
||||
EXPECT_TRUE(archive->IsFileExist("@usercache@/foundit.dat"));
|
||||
EXPECT_FALSE(archive->IsFileExist("@usercache@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@usercache@/foundit.dat", AZ::IO::FileSearchLocation::OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@usercache@/notfoundit.dat"));
|
||||
EXPECT_TRUE(archive->ClosePack(realNameBuf));
|
||||
|
||||
@@ -793,7 +793,7 @@ namespace UnitTest
|
||||
EXPECT_TRUE(archive->OpenPack("@products@", realNameBuf));
|
||||
EXPECT_TRUE(archive->IsFileExist("@products@/foundit.dat"));
|
||||
EXPECT_FALSE(archive->IsFileExist("@usercache@/foundit.dat")); // do not find it in the previous location!
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat", AZ::IO::FileSearchLocation::OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/notfoundit.dat"));
|
||||
EXPECT_TRUE(archive->ClosePack(realNameBuf));
|
||||
|
||||
@@ -802,8 +802,8 @@ namespace UnitTest
|
||||
EXPECT_TRUE(archive->IsFileExist("@products@/mystuff/foundit.dat"));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat")); // do not find it in the previous locations!
|
||||
EXPECT_FALSE(archive->IsFileExist("@usercache@/foundit.dat")); // do not find it in the previous locations!
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/mystuff/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat", AZ::IO::FileSearchLocation::OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/mystuff/foundit.dat", AZ::IO::FileSearchLocation::OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/notfoundit.dat")); // non-existent file
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/mystuff/notfoundit.dat")); // non-existent file
|
||||
EXPECT_TRUE(archive->ClosePack(realNameBuf));
|
||||
|
||||
+4
-4
@@ -202,9 +202,9 @@ namespace AzToolsFramework
|
||||
AZ_TracePrintf(logWindowName, "Creating new asset bundle manifest file \"%s\" for source pak \"%s\".\n", AzFramework::AssetBundleManifest::s_manifestFileName, sourcePak.c_str());
|
||||
bool manifestSaved = false;
|
||||
AZStd::string manifestDirectory;
|
||||
AZStd::vector<AZStd::string> levelDirs;
|
||||
AzFramework::StringFunc::Path::GetFullPath(sourcePak.c_str(), manifestDirectory);
|
||||
AssetCatalogRequestBus::BroadcastResult(manifestSaved, &AssetCatalogRequestBus::Events::CreateBundleManifest, outCatalogPath, AZStd::vector<AZStd::string>(), manifestDirectory, AzFramework::AssetBundleManifest::CurrentBundleVersion, levelDirs);
|
||||
AssetCatalogRequestBus::BroadcastResult(manifestSaved, &AssetCatalogRequestBus::Events::CreateBundleManifest, outCatalogPath,
|
||||
AZStd::vector<AZStd::string>(), manifestDirectory, AzFramework::AssetBundleManifest::CurrentBundleVersion, AZStd::vector<AZ::IO::Path>{});
|
||||
|
||||
AZStd::string manifestPath;
|
||||
AzFramework::StringFunc::Path::Join(manifestDirectory.c_str(), AzFramework::AssetBundleManifest::s_manifestFileName, manifestPath);
|
||||
@@ -263,7 +263,7 @@ namespace AzToolsFramework
|
||||
AZStd::string tempBundleFilePath = bundleFilePath.Native() + "_temp";
|
||||
|
||||
AZStd::vector<AZStd::string> dependentBundleNames;
|
||||
AZStd::vector<AZStd::string> levelDirs;
|
||||
AZStd::vector<AZ::IO::Path> levelDirs;
|
||||
AZStd::vector<AZStd::pair<AZStd::string, AZStd::string>> bundlePathDeltaCatalogPair;
|
||||
bundlePathDeltaCatalogPair.emplace_back(AZStd::make_pair(tempBundleFilePath, DeltaCatalogName));
|
||||
|
||||
@@ -515,7 +515,7 @@ namespace AzToolsFramework
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AssetBundleComponent::AddManifestFileToBundles(const AZStd::vector<AZStd::pair<AZStd::string, AZStd::string>>& bundlePathDeltaCatalogPair, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& bundleFolder, const AzToolsFramework::AssetBundleSettings& assetBundleSettings, const AZStd::vector<AZStd::string>& levelDirs)
|
||||
bool AssetBundleComponent::AddManifestFileToBundles(const AZStd::vector<AZStd::pair<AZStd::string, AZStd::string>>& bundlePathDeltaCatalogPair, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& bundleFolder, const AzToolsFramework::AssetBundleSettings& assetBundleSettings, const AZStd::vector<AZ::IO::Path>& levelDirs)
|
||||
{
|
||||
if (!MakePath(bundleFolder))
|
||||
{
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace AzToolsFramework
|
||||
|
||||
//! Adds the manifest file to all the bundles
|
||||
//! The parent bundle manifest file is special since it will contain information of all dependent bundles names.
|
||||
bool AddManifestFileToBundles(const AZStd::vector<AZStd::pair<AZStd::string, AZStd::string>>& bundlePathDeltaCatalogPair, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& bundleFolder, const AzToolsFramework::AssetBundleSettings& assetBundleSettings, const AZStd::vector<AZStd::string>& levelDirs);
|
||||
bool AddManifestFileToBundles(const AZStd::vector<AZStd::pair<AZStd::string, AZStd::string>>& bundlePathDeltaCatalogPair, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& bundleFolder, const AzToolsFramework::AssetBundleSettings& assetBundleSettings, const AZStd::vector<AZ::IO::Path>& levelDirs);
|
||||
|
||||
//! Adds the delta catalog and any remaining files to the bundle
|
||||
//! We only create the delta catalog once we are sure about what all the files that will go in it.
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@ namespace AzToolsFramework
|
||||
return AssetCatalog::RemoveDeltaCatalog(deltaCatalog);
|
||||
}
|
||||
|
||||
bool PlatformAddressedAssetCatalog::CreateBundleManifest(const AZStd::string& deltaCatalogPath, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& fileDirectory, int bundleVersion, const AZStd::vector<AZStd::string>& levelDirs)
|
||||
bool PlatformAddressedAssetCatalog::CreateBundleManifest(const AZStd::string& deltaCatalogPath, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& fileDirectory, int bundleVersion, const AZStd::vector<AZ::IO::Path>& levelDirs)
|
||||
{
|
||||
return AssetCatalog::CreateBundleManifest(deltaCatalogPath, dependentBundleNames, fileDirectory, bundleVersion, levelDirs);
|
||||
}
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ namespace AzToolsFramework
|
||||
bool InsertDeltaCatalogBefore(AZStd::shared_ptr<AzFramework::AssetRegistry> deltaCatalog, AZStd::shared_ptr<AzFramework::AssetRegistry> afterDeltaCatalog) override;
|
||||
bool RemoveDeltaCatalog(AZStd::shared_ptr<AzFramework::AssetRegistry> deltaCatalog) override;
|
||||
|
||||
bool CreateBundleManifest(const AZStd::string& deltaCatalogPath, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& fileDirectory, int bundleVersion, const AZStd::vector<AZStd::string>& levelDirs) override;
|
||||
bool CreateBundleManifest(const AZStd::string& deltaCatalogPath, const AZStd::vector<AZStd::string>& dependentBundleNames, const AZStd::string& fileDirectory, int bundleVersion, const AZStd::vector<AZ::IO::Path>& levelDirs) override;
|
||||
bool CreateDeltaCatalog(const AZStd::vector<AZStd::string>& files, const AZStd::string& filePath) override;
|
||||
void AddExtension(const char* extension) override;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzFramework/Archive/ArchiveVars.h>
|
||||
#include <AzFramework/Archive/INestedArchive.h>
|
||||
#include <AzFramework/Archive/IArchive.h>
|
||||
#include <CryCommon/platform.h>
|
||||
@@ -52,11 +53,11 @@ struct CryPakMock
|
||||
MOCK_METHOD1(PoolMalloc, void*(size_t size));
|
||||
MOCK_METHOD1(PoolFree, void(void* p));
|
||||
MOCK_METHOD3(PoolAllocMemoryBlock, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> (size_t nSize, const char* sUsage, size_t nAlign));
|
||||
MOCK_METHOD2(FindFirst, AZ::IO::ArchiveFileIterator(AZStd::string_view pDir, AZ::IO::IArchive::EFileSearchType));
|
||||
MOCK_METHOD2(FindFirst, AZ::IO::ArchiveFileIterator(AZStd::string_view pDir, AZ::IO::FileSearchLocation));
|
||||
MOCK_METHOD1(FindNext, AZ::IO::ArchiveFileIterator(AZ::IO::ArchiveFileIterator handle));
|
||||
MOCK_METHOD1(FindClose, bool(AZ::IO::ArchiveFileIterator));
|
||||
MOCK_METHOD1(GetModificationTime, AZ::IO::IArchive::FileTime(AZ::IO::HandleType f));
|
||||
MOCK_METHOD2(IsFileExist, bool(AZStd::string_view sFilename, EFileSearchLocation));
|
||||
MOCK_METHOD2(IsFileExist, bool(AZStd::string_view sFilename, AZ::IO::FileSearchLocation));
|
||||
MOCK_METHOD1(IsFolder, bool(AZStd::string_view sPath));
|
||||
MOCK_METHOD1(GetFileSizeOnDisk, AZ::IO::IArchive::SignedFileSize(AZStd::string_view filename));
|
||||
MOCK_METHOD4(OpenArchive, AZStd::intrusive_ptr<AZ::IO::INestedArchive> (AZStd::string_view szPath, AZStd::string_view bindRoot, uint32_t nFlags, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData));
|
||||
@@ -72,7 +73,7 @@ struct CryPakMock
|
||||
MOCK_METHOD1(UnregisterFileAccessSink, void(AZ::IO::IArchiveFileAccessSink * pSink));
|
||||
MOCK_METHOD1(DisableRuntimeFileAccess, void(bool status));
|
||||
MOCK_METHOD2(DisableRuntimeFileAccess, bool(bool status, AZStd::thread_id threadId));
|
||||
MOCK_CONST_METHOD0(GetPakPriority, AZ::IO::ArchiveLocationPriority());
|
||||
MOCK_CONST_METHOD0(GetPakPriority, AZ::IO::FileSearchPriority());
|
||||
MOCK_CONST_METHOD1(GetFileOffsetOnMedia, uint64_t(AZStd::string_view szName));
|
||||
MOCK_CONST_METHOD1(GetFileMediaType, EStreamSourceMediaType(AZStd::string_view szName));
|
||||
MOCK_METHOD0(GetLevelPackOpenEvent, auto()->LevelPackOpenEvent*);
|
||||
|
||||
@@ -203,24 +203,22 @@ CLevelSystem::CLevelSystem(ISystem* pSystem, const char* levelsFolder)
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto pPak = gEnv->pCryPak;
|
||||
auto archive = AZ::Interface<AZ::IO::IArchive>::Get();
|
||||
|
||||
if (AZ::IO::IArchive::LevelPackOpenEvent* levelPakOpenEvent = pPak->GetLevelPackOpenEvent())
|
||||
if (AZ::IO::IArchive::LevelPackOpenEvent* levelPakOpenEvent = archive->GetLevelPackOpenEvent())
|
||||
{
|
||||
m_levelPackOpenHandler = AZ::IO::IArchive::LevelPackOpenEvent::Handler([this](const AZStd::vector<AZStd::string>& levelDirs)
|
||||
m_levelPackOpenHandler = AZ::IO::IArchive::LevelPackOpenEvent::Handler([this](const AZStd::vector<AZ::IO::Path>& levelDirs)
|
||||
{
|
||||
for (AZStd::string dir : levelDirs)
|
||||
for (AZ::IO::Path levelDir : levelDirs)
|
||||
{
|
||||
AZ::StringFunc::Path::StripComponent(dir, true);
|
||||
AZStd::string searchPattern = dir + AZ_FILESYSTEM_SEPARATOR_WILDCARD;
|
||||
bool modFolder = false;
|
||||
PopulateLevels(searchPattern, dir, gEnv->pCryPak, modFolder, false);
|
||||
PopulateLevels((levelDir / "*").Native(), levelDir.Native(), AZ::Interface<AZ::IO::IArchive>::Get(), modFolder, false);
|
||||
}
|
||||
});
|
||||
m_levelPackOpenHandler.Connect(*levelPakOpenEvent);
|
||||
}
|
||||
|
||||
if (AZ::IO::IArchive::LevelPackCloseEvent* levelPakCloseEvent = pPak->GetLevelPackCloseEvent())
|
||||
if (AZ::IO::IArchive::LevelPackCloseEvent* levelPakCloseEvent = archive->GetLevelPackCloseEvent())
|
||||
{
|
||||
m_levelPackCloseHandler = AZ::IO::IArchive::LevelPackCloseEvent::Handler([this](AZStd::string_view)
|
||||
{
|
||||
@@ -288,7 +286,7 @@ void CLevelSystem::ScanFolder(const char* subfolder, bool modFolder)
|
||||
|
||||
AZStd::unordered_set<AZStd::string> pakList;
|
||||
|
||||
AZ::IO::ArchiveFileIterator handle = pPak->FindFirst(search.c_str(), AZ::IO::IArchive::eFileSearchType_AllowOnDiskOnly);
|
||||
AZ::IO::ArchiveFileIterator handle = pPak->FindFirst(search.c_str(), AZ::IO::FileSearchLocation::OnDisk);
|
||||
|
||||
if (handle)
|
||||
{
|
||||
@@ -335,86 +333,85 @@ void CLevelSystem::ScanFolder(const char* subfolder, bool modFolder)
|
||||
}
|
||||
|
||||
void CLevelSystem::PopulateLevels(
|
||||
AZStd::string searchPattern, AZStd::string& folder, AZ::IO::IArchive* pPak, bool& modFolder, bool fromFileSystemOnly)
|
||||
AZStd::string searchPattern, const AZStd::string& folder, AZ::IO::IArchive* pPak, bool& modFolder, bool fromFileSystemOnly)
|
||||
{
|
||||
// allow this find first to actually touch the file system
|
||||
// (causes small overhead but with minimal amount of levels this should only be around 150ms on actual DVD Emu)
|
||||
AZ::IO::ArchiveFileIterator handle = pPak->FindFirst(searchPattern.c_str(),
|
||||
fromFileSystemOnly ? AZ::IO::FileSearchLocation::OnDisk : AZ::IO::FileSearchLocation::InPak);
|
||||
|
||||
if (handle)
|
||||
{
|
||||
// allow this find first to actually touch the file system
|
||||
// (causes small overhead but with minimal amount of levels this should only be around 150ms on actual DVD Emu)
|
||||
AZ::IO::ArchiveFileIterator handle = pPak->FindFirst(searchPattern.c_str(), AZ::IO::IArchive::eFileSearchType_AllowOnDiskOnly);
|
||||
|
||||
if (handle)
|
||||
do
|
||||
{
|
||||
do
|
||||
if ((handle.m_fileDesc.nAttrib & AZ::IO::FileDesc::Attribute::Subdirectory) != AZ::IO::FileDesc::Attribute::Subdirectory ||
|
||||
handle.m_filename == "." || handle.m_filename == "..")
|
||||
{
|
||||
if ((handle.m_fileDesc.nAttrib & AZ::IO::FileDesc::Attribute::Subdirectory) != AZ::IO::FileDesc::Attribute::Subdirectory ||
|
||||
handle.m_filename == "." || handle.m_filename == "..")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
AZStd::string levelFolder;
|
||||
if (fromFileSystemOnly)
|
||||
{
|
||||
levelFolder =
|
||||
(folder.empty() ? "" : (folder + "/")) + AZStd::string(handle.m_filename.data(), handle.m_filename.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::string levelName(AZ::IO::PathView(handle.m_filename).Filename().Native());
|
||||
levelFolder = (folder.empty() ? "" : (folder + "/")) + levelName;
|
||||
}
|
||||
AZStd::string levelFolder;
|
||||
if (fromFileSystemOnly)
|
||||
{
|
||||
levelFolder =
|
||||
(folder.empty() ? "" : (folder + "/")) + AZStd::string(handle.m_filename.data(), handle.m_filename.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::string levelName(AZ::IO::PathView(handle.m_filename).Filename().Native());
|
||||
levelFolder = (folder.empty() ? "" : (folder + "/")) + levelName;
|
||||
}
|
||||
|
||||
AZStd::string levelPath;
|
||||
if (AZ::StringFunc::StartsWith(levelFolder.c_str(), m_levelsFolder.c_str()))
|
||||
AZStd::string levelPath;
|
||||
if (AZ::StringFunc::StartsWith(levelFolder.c_str(), m_levelsFolder.c_str()))
|
||||
{
|
||||
levelPath = levelFolder;
|
||||
}
|
||||
else
|
||||
{
|
||||
levelPath = m_levelsFolder + "/" + levelFolder;
|
||||
}
|
||||
|
||||
const AZStd::string levelPakName = levelPath + "/" + LevelPakName;
|
||||
const AZStd::string levelInfoName = levelPath + "/levelinfo.xml";
|
||||
|
||||
if (!pPak->IsFileExist(
|
||||
levelPakName.c_str(),
|
||||
fromFileSystemOnly ? AZ::IO::FileSearchLocation::OnDisk : AZ::IO::FileSearchLocation::InPak) &&
|
||||
!pPak->IsFileExist(
|
||||
levelInfoName.c_str(),
|
||||
fromFileSystemOnly ? AZ::IO::FileSearchLocation::OnDisk : AZ::IO::FileSearchLocation::InPak))
|
||||
{
|
||||
ScanFolder(levelFolder.c_str(), modFolder);
|
||||
continue;
|
||||
}
|
||||
|
||||
// With the level.pak workflow, levelPath and levelName will point to a directory.
|
||||
// levelPath: levels/mylevel
|
||||
// levelName: mylevel
|
||||
CLevelInfo levelInfo;
|
||||
levelInfo.m_levelPath = levelPath;
|
||||
levelInfo.m_levelName = levelFolder;
|
||||
levelInfo.m_isPak = !fromFileSystemOnly;
|
||||
|
||||
CLevelInfo* pExistingInfo = GetLevelInfoInternal(levelInfo.m_levelName);
|
||||
|
||||
// Don't add the level if it is already in the list
|
||||
if (pExistingInfo == NULL)
|
||||
{
|
||||
m_levelInfos.push_back(levelInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Levels in bundles take priority over levels outside bundles.
|
||||
if (!pExistingInfo->m_isPak && levelInfo.m_isPak)
|
||||
{
|
||||
levelPath = levelFolder;
|
||||
}
|
||||
else
|
||||
{
|
||||
levelPath = m_levelsFolder + "/" + levelFolder;
|
||||
*pExistingInfo = levelInfo;
|
||||
}
|
||||
}
|
||||
} while (handle = pPak->FindNext(handle));
|
||||
|
||||
const AZStd::string levelPakName = levelPath + "/" + LevelPakName;
|
||||
const AZStd::string levelInfoName = levelPath + "/levelinfo.xml";
|
||||
|
||||
if (!pPak->IsFileExist(
|
||||
levelPakName.c_str(),
|
||||
fromFileSystemOnly ? AZ::IO::IArchive::eFileLocation_OnDisk : AZ::IO::IArchive::eFileLocation_InPak) &&
|
||||
!pPak->IsFileExist(
|
||||
levelInfoName.c_str(),
|
||||
fromFileSystemOnly ? AZ::IO::IArchive::eFileLocation_OnDisk : AZ::IO::IArchive::eFileLocation_InPak))
|
||||
{
|
||||
ScanFolder(levelFolder.c_str(), modFolder);
|
||||
continue;
|
||||
}
|
||||
|
||||
// With the level.pak workflow, levelPath and levelName will point to a directory.
|
||||
// levelPath: levels/mylevel
|
||||
// levelName: mylevel
|
||||
CLevelInfo levelInfo;
|
||||
levelInfo.m_levelPath = levelPath;
|
||||
levelInfo.m_levelName = levelFolder;
|
||||
levelInfo.m_isPak = !fromFileSystemOnly;
|
||||
|
||||
CLevelInfo* pExistingInfo = GetLevelInfoInternal(levelInfo.m_levelName);
|
||||
|
||||
// Don't add the level if it is already in the list
|
||||
if (pExistingInfo == NULL)
|
||||
{
|
||||
m_levelInfos.push_back(levelInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Levels in bundles take priority over levels outside bundles.
|
||||
if (!pExistingInfo->m_isPak && levelInfo.m_isPak)
|
||||
{
|
||||
*pExistingInfo = levelInfo;
|
||||
}
|
||||
}
|
||||
} while (handle = pPak->FindNext(handle));
|
||||
|
||||
pPak->FindClose(handle);
|
||||
}
|
||||
pPak->FindClose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ private:
|
||||
|
||||
void ScanFolder(const char* subfolder, bool modFolder);
|
||||
void PopulateLevels(
|
||||
AZStd::string searchPattern, AZStd::string& folder, AZ::IO::IArchive* pPak, bool& modFolder, bool fromFileSystemOnly);
|
||||
AZStd::string searchPattern, const AZStd::string& folder, AZ::IO::IArchive* pPak, bool& modFolder, bool fromFileSystemOnly);
|
||||
void PrepareNextLevel(const char* levelName);
|
||||
ILevel* LoadLevelInternal(const char* _levelName);
|
||||
|
||||
|
||||
@@ -170,14 +170,6 @@ void CryEngineSignalHandler(int signal)
|
||||
extern HMODULE gDLLHandle;
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
// on windows, we lock our cache using a lockfile. On other platforms this is not necessary since devices like ios, android, consoles cannot
|
||||
// run more than one game process that uses the same folder anyway.
|
||||
HANDLE g_cacheLock = INVALID_HANDLE_VALUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
//static int g_sysSpecChanged = false;
|
||||
|
||||
@@ -339,9 +331,6 @@ bool CSystem::InitFileSystem()
|
||||
m_pUserCallback->OnInitProgress("Initializing File System...");
|
||||
}
|
||||
|
||||
// get the DirectInstance FileIOBase which should be the AZ::LocalFileIO
|
||||
m_env.pFileIO = AZ::IO::FileIOBase::GetDirectInstance();
|
||||
|
||||
m_env.pCryPak = AZ::Interface<AZ::IO::IArchive>::Get();
|
||||
m_env.pFileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
AZ_Assert(m_env.pCryPak, "CryPak has not been initialized on AZ::Interface");
|
||||
@@ -365,33 +354,6 @@ bool CSystem::InitFileSystem()
|
||||
|
||||
void CSystem::ShutdownFileSystem()
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
if (g_cacheLock != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(g_cacheLock);
|
||||
g_cacheLock = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
using namespace AZ::IO;
|
||||
|
||||
FileIOBase* directInstance = FileIOBase::GetDirectInstance();
|
||||
FileIOBase* pakInstance = FileIOBase::GetInstance();
|
||||
|
||||
if (directInstance == m_env.pFileIO)
|
||||
{
|
||||
// we only mess with file io if we own the instance that we installed.
|
||||
// if we dont' own the instance, then we never configured fileIO and we should not alter it.
|
||||
delete directInstance;
|
||||
FileIOBase::SetDirectInstance(nullptr);
|
||||
|
||||
if (pakInstance != directInstance)
|
||||
{
|
||||
delete pakInstance;
|
||||
FileIOBase::SetInstance(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
m_env.pFileIO = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,10 @@ ly_add_target(
|
||||
${additional_dependencies}
|
||||
)
|
||||
|
||||
if(LY_DEFAULT_PROJECT_PATH)
|
||||
set_property(TARGET AssetBundler AssetBundlerBatch APPEND PROPERTY VS_DEBUGGER_COMMAND_ARGUMENTS "--project-path=\"${LY_DEFAULT_PROJECT_PATH}\"")
|
||||
endif()
|
||||
|
||||
# Adds a specialized .setreg to identify gems enabled in the active project.
|
||||
# This associates the AssetBundler target with the .Builders gem variants.
|
||||
ly_set_gem_variant_to_load(TARGETS AssetBundler VARIANTS Builders)
|
||||
|
||||
@@ -10,5 +10,8 @@
|
||||
|
||||
set(LY_ASSET_DEPLOY_MODE "LOOSE" CACHE STRING "Set the Asset deployment when deploying to the target platform (LOOSE, PAK, VFS)")
|
||||
set(LY_ASSET_OVERRIDE_PAK_FOLDER_ROOT "" CACHE STRING "Optional root path to where Pak file folders are stored. By default, blank will use a predefined 'paks' root.")
|
||||
|
||||
|
||||
set(LY_ARCHIVE_FILE_SEARCH_MODE "$<$<CONFIG:release>:2>" CACHE STRING "Set the default file search mode to locate non-Pak files within the Archive System\n\
|
||||
Valid values are:\n\
|
||||
0 = Search FileSystem first, before searching within mounted Paks\n\
|
||||
1 = Search mounted Paks first, before searching FileSystem\n\
|
||||
2 = Search only mounted Paks(default in release)\n")
|
||||
|
||||
@@ -653,36 +653,6 @@ function(ly_add_source_properties)
|
||||
endfunction()
|
||||
|
||||
|
||||
#! ly_project_add_subdirectory: calls add_subdirectory() if the project name is in the project list
|
||||
#
|
||||
# This can be useful when including subdirs in the restricted folder only if the project is in the project list
|
||||
# If you give it a second parameter it will add_subdirectory using that instead, if the project is in the project list
|
||||
#
|
||||
# add_subdirectory(AutomatedTesting) if Automatedtesting is in the project list
|
||||
# EX. ly_project_add_subdirectory(AutomatedTesting)
|
||||
#
|
||||
# add_subdirectory(SamplesProject) if Automatedtesting is in the project list
|
||||
# EX. ly_project_add_subdirectory(AutomatedTesting SamplesProject)
|
||||
#
|
||||
# \arg:project_name the name of the project that may be enabled
|
||||
# \arg:binary_project_dir optional, if supplied that binary_project_dir will be added when project name is enabled.
|
||||
#
|
||||
function(ly_project_add_subdirectory project_name)
|
||||
if(${project_name} IN_LIST LY_PROJECTS)
|
||||
if(ARGC GREATER 1)
|
||||
list(GET ARGN 0 subdir)
|
||||
endif()
|
||||
if(ARGC GREATER 2)
|
||||
list(GET ARGN 1 binary_project_dir)
|
||||
endif()
|
||||
if(subdir)
|
||||
add_subdirectory(${subdir} ${binary_project_dir})
|
||||
else()
|
||||
add_subdirectory(${project_name} ${binary_project_dir})
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# given a target name, returns the "real" name of the target if its an alias.
|
||||
# this function recursively de-aliases
|
||||
function(ly_de_alias_target target_name output_variable_name)
|
||||
|
||||
Reference in New Issue
Block a user