Browse Source

Archive Component - Rewrite and additional work on Archive and Asset Bundler (#4332)

* Fix issues with seedlist for AutomatedTesting

Fixes error reporting so it will show the file hint in the tool.
Removes any missing assets from the .seed file.
Remove an unnecessary dependency from AutomatedTesting dependencies
file.

Signed-off-by: amzn-phist <[email protected]>

* Make ArchiveComponent use AZ::IO::IArchive

Initial changes that will get the sychronous calls in ArchiveComponent
to use IArchive interface rather than external zip/7z tools.

Some of the asynchronous api are still in place, anything that wasn't
being used has been removed for now.  This may change later if we move
towards all the api being asynchronous.  Until then, we can't remove the
reliance upon the external archive tools completely.

Signed-off-by: amzn-phist <[email protected]>

* Updates AZStd::thread constructors

Adds a variadic constructor which forwards args to the functor.
Because of our thread_desc extension, there was confusion on the
arugments, so the args were reordered to take the thread_desc first,
before the functor and args.
Also the thread_desc is taken as reference rather than by pointer.
Update callsites to account for this change.

Signed-off-by: amzn-phist <[email protected]>

* Async operation of ArchiveComponent api

This sets up the ArchiveComponent to operate asynchronously.  It uses
promise/future to transfer results to caller.

This is still broken, there's a few things that need to get fixed up,
but this is a good checkpoint for the work as it solidifies the api,
cleans up a bunch of unused code, and compiles.

Signed-off-by: amzn-phist <[email protected]>

* Removes the platform-specific ArchiveComponen

These are no longer needed, as they control the direct interaction with
host OS tools like 7za.exe or /bin/zip.

Signed-off-by: amzn-phist <[email protected]>

* Removes the platform-specific files from cmake

Signed-off-by: amzn-phist <[email protected]>

* Removes the 7za.exe (and legal notice)

This tool is no longer needed in the repo.

Signed-off-by: amzn-phist <[email protected]>

* Fixes usage of IArchive::GetFullPath()

This changed to return a PathView, updated to reflect that.

Signed-off-by: amzn-phist <[email protected]>

* Fix promises and threads

Make sure promises are only set exactly once.  This meant reworking some
of the initial error checking.
Detach threads when created.  Adds [[nodiscard]] to the functions that
return a future.  Since threads are detached, the future is the main way
to get communication from the thread.
Clean up interface, add comments.

Signed-off-by: amzn-phist <[email protected]>

* More edits to thread creation

Changes to thread construction to account for parameter change.

Signed-off-by: amzn-phist <[email protected]>

* Fix some remaining issues with ArchiveComponent

Put created threads inside a container, then join them at Deactivate.
Fix asset bundler case when injecting a file with no working directory.
Fix thread constructor that applies args to a function.
Fix lambdas to take string args by value rather than reference.

Signed-off-by: amzn-phist <[email protected]>

* Fixes some remaining bugs in ArchiveComponent

Open archive as read-only during extract & list operations.
Fixes paths issues.

Signed-off-by: amzn-phist <[email protected]>

* Fix initialize of opaque thread handle in thread_UnixLike.h

Signed-off-by: lumberyard-employee-dm <[email protected]>

* Removed unused variable in AssetBundleComponent.cpp to fix compiler warning

Signed-off-by: lumberyard-employee-dm <[email protected]>

* Fix some issues with archives

File paths in the CDR and the local headers need to match, but there
were issues with path separators and case that made it possible to get
invalid headers errors in some archives.

Signed-off-by: amzn-phist <[email protected]>

* Adds some new ArchiveComponent unit tests

Adds new tests for extraction of archive and adding files from a file
list to an archive.

Signed-off-by: amzn-phist <[email protected]>

* Fix file data offset issues when opening archives

When opening an INestedArchive it would run through the CDR headers to
create file entries in the zip cache.  The offsets to the compressed
data were being calculated incorrectly because they were using the CDR
headers rather than jumping to the local file headers and getting
offsets from those sizes.

Removed and refactored some archive validation flow and zip cache
factory init methods to either init default or init w/ additional
validation checks.

Signed-off-by: amzn-phist <[email protected]>

* Addresses PR feedback

Signed-off-by: amzn-phist <[email protected]>

* Address more points of feedback in PR

Signed-off-by: amzn-phist <[email protected]>

* Address additional PR feedback

 Fixes up some error checks and uses of strings vs paths.
 Enable archive component tests on Linux so we can see if they will
 pass.

Signed-off-by: amzn-phist <[email protected]>

* Address PR feedback

Change the INestedArchive interface to list files as AZ::IO::Path.

Signed-off-by: amzn-phist <[email protected]>

* Disabling the ArchiveComponent tests on Linux

They failed so we will revisit them to attempt a fix.

Signed-off-by: amzn-phist <[email protected]>

* Rename a member variable to be more accurate

Signed-off-by: amzn-phist <[email protected]>

* Address feedback on PR

Bump version of Archive Components for serialize context.
Improve error messages during archive open and validation.

Signed-off-by: amzn-phist <[email protected]>

* Revert recent changes

Signed-off-by: amzn-phist <[email protected]>

Co-authored-by: lumberyard-employee-dm <[email protected]>
amzn-phist 3 years ago
parent
commit
fec77632ef
57 changed files with 1158 additions and 2550 deletions
  1. 18 922
      Assets/Engine/SeedAssetList.seed
  2. 0 1
      AutomatedTesting/AutomatedTesting_Dependencies.xml
  3. 6 4
      Code/Framework/AzCore/AzCore/IO/Streamer/Scheduler.cpp
  4. 2 2
      Code/Framework/AzCore/AzCore/Jobs/Internal/JobManagerWorkStealing.cpp
  5. 3 3
      Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp
  6. 11 8
      Code/Framework/AzCore/AzCore/std/parallel/thread.h
  7. 15 5
      Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/std/parallel/internal/thread_UnixLike.h
  8. 15 4
      Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/internal/thread_WinAPI.h
  9. 77 77
      Code/Framework/AzCore/Tests/AZStd/Parallel.cpp
  10. 5 5
      Code/Framework/AzCore/Tests/Memory.cpp
  11. 9 7
      Code/Framework/AzFramework/AzFramework/Application/Application.cpp
  12. 14 1
      Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp
  13. 13 0
      Code/Framework/AzFramework/AzFramework/Archive/INestedArchive.h
  14. 40 0
      Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.cpp
  15. 7 2
      Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.h
  16. 12 1
      Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp
  17. 64 138
      Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.cpp
  18. 3 25
      Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.h
  19. 2 2
      Code/Framework/AzFramework/AzFramework/Archive/ZipDirList.cpp
  20. 24 11
      Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.h
  21. 1 1
      Code/Framework/AzFramework/AzFramework/Network/AssetProcessorConnection.cpp
  22. 1 1
      Code/Framework/AzFramework/AzFramework/TargetManagement/TargetManagementComponent.cpp
  23. 20 18
      Code/Framework/AzNetworking/AzNetworking/Utilities/TimedThread.cpp
  24. 62 73
      Code/Framework/AzToolsFramework/AzToolsFramework/Archive/ArchiveAPI.h
  25. 452 312
      Code/Framework/AzToolsFramework/AzToolsFramework/Archive/ArchiveComponent.cpp
  26. 45 49
      Code/Framework/AzToolsFramework/AzToolsFramework/Archive/ArchiveComponent.h
  27. 30 59
      Code/Framework/AzToolsFramework/AzToolsFramework/Archive/NullArchiveComponent.cpp
  28. 26 18
      Code/Framework/AzToolsFramework/AzToolsFramework/Archive/NullArchiveComponent.h
  29. 17 10
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBundle/AssetBundleComponent.cpp
  30. 1 1
      Code/Framework/AzToolsFramework/AzToolsFramework/AssetBundle/AssetBundleComponent.h
  31. 0 230
      Code/Framework/AzToolsFramework/Platform/Linux/AzToolsFramework/Archive/ArchiveComponent_Linux.cpp
  32. 0 1
      Code/Framework/AzToolsFramework/Platform/Linux/platform_linux_files.cmake
  33. 0 263
      Code/Framework/AzToolsFramework/Platform/Mac/AzToolsFramework/Archive/ArchiveComponent_Mac.cpp
  34. 0 1
      Code/Framework/AzToolsFramework/Platform/Mac/platform_mac_files.cmake
  35. 0 167
      Code/Framework/AzToolsFramework/Platform/Windows/AzToolsFramework/Archive/ArchiveComponent_Windows.cpp
  36. 0 1
      Code/Framework/AzToolsFramework/Platform/Windows/platform_windows_files.cmake
  37. 104 22
      Code/Framework/AzToolsFramework/Tests/ArchiveTests.cpp
  38. 1 1
      Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp
  39. 1 1
      Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp
  40. 2 1
      Code/Tools/AssetBundler/source/models/SeedListTableModel.cpp
  41. 1 1
      Code/Tools/AssetProcessor/AssetBuilder/AssetBuilderComponent.cpp
  42. 2 2
      Code/Tools/AssetProcessor/native/tests/AssetCatalog/AssetCatalogUnitTests.cpp
  43. 16 8
      Code/Tools/AssetProcessor/native/utilities/AssetServerHandler.cpp
  44. 1 1
      Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp
  45. 1 1
      Gems/Atom/RHI/Code/Source/RHI/AsyncWorkQueue.cpp
  46. 1 1
      Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp
  47. 2 2
      Gems/Atom/RHI/Code/Source/RHI/Fence.cpp
  48. 2 3
      Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp
  49. 1 1
      Gems/AudioSystem/Code/Source/Engine/AudioSystem.cpp
  50. 1 1
      Gems/BarrierInput/Code/Source/BarrierInputClient.cpp
  51. 1 1
      Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp
  52. 9 26
      Gems/LmbrCentral/Code/Source/Builders/LevelBuilder/LevelBuilderWorker.cpp
  53. 1 1
      Gems/Microphone/Code/Source/Platform/Windows/MicrophoneSystemComponent_Windows.cpp
  54. 1 1
      Gems/PhysX/Code/Tests/PhysXMultithreadingTest.cpp
  55. 15 13
      Gems/SaveData/Code/Source/SaveDataSystemComponent.cpp
  56. 0 3
      Tools/7za.exe
  57. 0 36
      Tools/7za_legal_notice.txt

+ 18 - 922
Assets/Engine/SeedAssetList.seed

@@ -66,779 +66,75 @@
 		</Class>
 		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
 			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{16983926-6160-5935-853E-641C8BBCFA1B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/codecoverage/hit.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{914896F1-D4A3-5550-9676-8B2D48443335}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/codecoverage/pbar.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{0E4737A6-2B5C-57DB-A0FC-38C2F84D970A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/codecoverage/unexpected.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{34B60E74-28FA-57C4-9A2E-77515A083AC5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/averagememoryusage.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{D84DBC88-3637-5876-B249-E92EA9BCD0F5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/highmemoryusage.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{98BA37F2-74C0-54CD-8109-F71276E834FE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/livepreview.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{DAC6670C-4A48-5661-B0DC-030071B2F2AB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/lowmemoryusage.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{9AF56C8A-4B9F-5B20-A77D-E30114E032D6}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/navigationprocessing.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{B6A22033-75B8-5580-80D7-0568C08AAFF3}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/nullsoundsystem.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{8AE41B60-4004-5749-8B50-5EF6E5151342}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/shadercompiling.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{B150AA1E-B38A-5827-AABE-A072E7C2477F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/streaming.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{F43241FB-ECDE-55A9-BA59-AE19AF495F62}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/streamingterrain.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{F0A47991-AE9A-5E6B-9B4B-0993FC73BB8D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/materials/fog/fogvolumebox.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{E2D5810A-A0A8-559D-813F-ED37F1660379}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/materials/fog/fogvolumeellipsoid.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{210E4B54-63B7-5F30-81B9-39371B298723}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/materials/fog/oceaninto.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{2C991928-0414-5CD8-BA07-CDBD57E9E5C1}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/materials/fog/oceanintolowspec.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{EA10CCB0-79E7-51E2-9585-B31B61716855}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/materials/fog/oceanoutof.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{E53D792D-A41F-54C2-AA9B-1609A5467588}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/materials/fog/oceanoutoflowspec.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{575105B0-7184-513D-966F-7932B52A24B6}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/materials/fog/waterfogvolumeinto.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{2119F7D0-5555-5A8E-8D4F-48225AA3C012}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/materials/fog/waterfogvolumeoutof.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{D4E71967-FCEA-516E-9DB5-96595569A4AB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/materials/physproxytoobig.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{EEE06764-1F83-59BE-8611-102F21B77076}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/materials/sky/sky.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{923F707E-9CE8-5B65-BB53-72AFB91B4165}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/materials/water/ocean_default.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{359148BF-8B82-51CE-8919-EB6E79A25596}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/materials/water/wateroceanbottom.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{04EF85E7-D3F5-5359-A52E-C59566B79C4F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/screenspace/areatex.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{60736D16-139A-5623-A49F-E33C91878CC5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/screenspace/film_grain.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{1AA9E7E9-6723-5394-88DA-04E9A1CAE19D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/screenspace/grain_bayer_mul.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{C47FD879-9E9D-5FED-A771-AA5DD3FBA1EB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/screenspace/normalsfitting.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{28ABA702-99F9-5B40-84EC-E297D0FB7BCC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/screenspace/pointsonsphere4x4.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{41E565F8-E384-5C8B-B34B-494A93FC4A15}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/screenspace/pointsonspherevo4x4.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{90B77841-601D-5CE3-9631-F4219CB561AC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/screenspace/searchtex.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{52162CD3-1245-5BF8-923F-E8CEC547B227}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="3000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/shading/defaultprobe_cm_ibldiffuse.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{52162CD3-1245-5BF8-923F-E8CEC547B227}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="2000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/shading/defaultprobe_cm_iblspecular.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{AFB81122-E810-5940-8C5C-BFC0E1BA0875}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/shading/environmentbrdf.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{A0F3C5F3-4D9C-5B27-A8D0-9DD98108B0C2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/shading/vignetting.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{5B87AD56-9EF7-5750-805D-76AC1C950D63}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/shading/waterfoam.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{4DFDF390-CC32-5BE8-BFAC-3BC65DC9E0E4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="255" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/sky/optical.lut" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{687C2588-8B67-57B6-BEB5-3D29143A624F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="255" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/sky/stars.dat" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{2D05A7E1-9A9D-593E-B1BE-ACFF1799FBBC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/defaultsolids_diff.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{493ACDCA-0393-5225-B48A-E355516F5E09}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/rcerror.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{B68E2732-F748-51C3-95BE-4D66073866A4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/rcerror_a.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{F74A817C-8493-556B-9C5E-9C55B2A6541C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="3000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/rcerror_cm_ibldiffuse.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{F74A817C-8493-556B-9C5E-9C55B2A6541C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="2000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/rcerror_cm_iblspecular.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{9A531C9D-0F6E-5FF4-B853-2BA03994054D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/rcerror_ddn.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{6A4CA27C-E194-5954-888C-F470924B8C9E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/rcerror_ddna.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{78C64FA5-267D-543F-87DC-8ACBA422B697}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/replacemecm.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{76C3ABD1-97B1-5010-8732-27469D27783A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/replacemerelease.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{45CF823D-491D-5C86-A1D1-E96F9B54BA5E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/shadercompiling.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{5AD90C79-0820-5667-98BA-3B81E8D8316E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/shadererror.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{30636215-C650-5FB5-97C3-DE456AF8B444}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/black.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{BA504C07-4568-51E8-AD95-41C6CAAABE71}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/blackalpha.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{FA447D02-C5E2-5688-AD42-839E03DF92FB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/blackcm.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{826DFAB8-AEA4-503C-A5DE-CC31100D5D2D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/caustics_sampler.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{A09C44AE-E326-5987-9200-00E18C24BAE4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/default_cch.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{80E55B1C-5970-55BA-859C-5650C1B63BA8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/flares/ghost_grey.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{DB73764D-3DCF-5CEE-BAF4-D4587CB14383}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/flares/icons/ghost.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{D5B8AC4E-5738-5573-BA28-8202D3CB00BA}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/flares/icons/glow.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{1616B1E9-CC73-5F2B-8231-6C7F715E6123}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/flares/icons/iris_shafts.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{C8259FF1-D83A-59D0-A011-2A05720C9E48}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/flares/icons/multi_ghost.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{13B4A9B8-8ED5-59BE-897C-CF457E645B85}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/flares/icons/orbs.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{573682BF-D4EC-5F4D-ADC8-CA9155A84537}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/flares/icons/ring.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{7A71C338-1EFF-5F32-B24D-638C330172AB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/flares/icons/vol_shafts.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{6DE56C27-13DD-5E06-A39C-51AA74368239}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/flares/iris_shaft.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{8E964EB9-9199-5FDE-B430-CBC06F1D036B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/flares/lens_dirtyglass.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{5F65364B-29BC-5952-B19B-63E4413251D0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/flares/orb_01.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{07FFB096-FE13-50F9-8D1A-136AF06A788A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/flares/spectrum_full.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{273044AE-6D8E-5BF9-AB52-27C56794DDDC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/fogvolshadowjitter.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{A57190FB-D213-523D-B0E3-80071CF8671B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/frozen/frost_noise3.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{9BCC8F01-F26E-50DC-BFEF-FB8BC9B5CDD0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/frozen/frost_noise4.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{F0645175-9ED4-5955-B382-E8B286EE272D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/frozen/snow_spatter.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{72118AD3-BFE6-5DB1-B54F-565C213EC097}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/glass_decalatlas_ddn.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{A45AFFA5-085F-5FC8-BA00-0D312894CE74}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/glass_decalatlas_diff.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{D1C27431-940A-5503-BC7D-24A02624954F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/grey.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{91871647-CCA0-5770-BFD1-D18DA323D766}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/jumpnoisehighfrequency_x27y19.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{2E988455-2098-589B-A851-9F3E06931E7B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/noise3d.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{01FC0C22-A53C-52A0-905F-C6116987CA7B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/noise.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{CE0D25F5-09B2-58BF-B402-0D2B57CDE94C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/oceanwaves_ddn.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{44018EF7-DE41-5B2F-ADE1-559A765267C4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/palletteinst.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{957B791A-EEC4-5FCA-BBB1-65BA19A7414F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/perlinnoise2d.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{CCF2215B-CA7B-52E6-984A-02A1A08C8752}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/perlinnoise_sum.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{0AD39162-29A6-5E35-B7D6-486187979ED7}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/perlinnoisederivatives.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{BC788487-7231-5685-A1D3-B99669088633}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/perlinnoisenormal_ddn.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{1186F215-63F9-5C9E-BBAE-48A803D0818A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/pixeltex.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{839CAA27-2D14-5B0F-8156-5A9A79CF0A33}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/rotrandomcm.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{62ADE3EE-022B-5729-B614-8F1960FC72BD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/screen_noisy_bump.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{35DB3C74-85EC-5F8C-A729-160126F53AA3}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/screenfrost_alpha.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{78836DF3-C8DE-538D-9CE8-3ACDB8B58D90}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/screenfrost_ddn.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{DD7CD22E-5686-5349-8D9D-35B8ED7FEADF}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/snowflakes.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{128F4EA1-6CC2-5B5C-BA7C-B6ED96F417AC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
+				<Class name="AZ::Uuid" field="guid" value="{34B60E74-28FA-57C4-9A2E-77515A083AC5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
 				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 			</Class>
 			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/startscreen.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/averagememoryusage.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 		</Class>
 		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
 			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{0D08102C-D5B0-5EEA-8FE5-50CB48384E2C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
+				<Class name="AZ::Uuid" field="guid" value="{D84DBC88-3637-5876-B249-E92EA9BCD0F5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
 				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 			</Class>
 			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/texelspermetergrad.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/highmemoryusage.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 		</Class>
 		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
 			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{9D76262A-B907-569D-828C-D1BA03DE4919}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
+				<Class name="AZ::Uuid" field="guid" value="{98BA37F2-74C0-54CD-8109-F71276E834FE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
 				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 			</Class>
 			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/user_tex1.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/livepreview.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 		</Class>
 		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
 			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{8ACBE475-82F1-52B6-B151-2F782D10AE88}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
+				<Class name="AZ::Uuid" field="guid" value="{DAC6670C-4A48-5661-B0DC-030071B2F2AB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
 				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 			</Class>
 			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/user_tex2.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/lowmemoryusage.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 		</Class>
 		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
 			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{9E9D05D2-C69B-584F-B567-54E0BBDB6D93}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
+				<Class name="AZ::Uuid" field="guid" value="{9AF56C8A-4B9F-5B20-A77D-E30114E032D6}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
 				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 			</Class>
 			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/vector_noise.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/navigationprocessing.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 		</Class>
 		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
 			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{BCBE61E6-CB5D-5EC8-9969-6BEE9D855F3D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
+				<Class name="AZ::Uuid" field="guid" value="{B6A22033-75B8-5580-80D7-0568C08AAFF3}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
 				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 			</Class>
 			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/water_droplets.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/nullsoundsystem.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 		</Class>
 		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
 			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{CA7B4C82-B514-58C7-A67D-B4ED5053E5C8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
+				<Class name="AZ::Uuid" field="guid" value="{8AE41B60-4004-5749-8B50-5EF6E5151342}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
 				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 			</Class>
 			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/water_gloss.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/shadercompiling.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 		</Class>
 		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
 			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{8AE9BA46-862B-5F85-94FD-F1C407B842A9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
+				<Class name="AZ::Uuid" field="guid" value="{B150AA1E-B38A-5827-AABE-A072E7C2477F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
 				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 			</Class>
 			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/white.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/streaming.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 		</Class>
 		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
 			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{D0A2B3B2-5C08-5F0D-A291-C49959B8E502}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
+				<Class name="AZ::Uuid" field="guid" value="{F43241FB-ECDE-55A9-BA59-AE19AF495F62}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
 				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 			</Class>
 			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/white_ddn.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+			<Class name="AZStd::string" field="pathHint" value="engineassets/icons/streamingterrain.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 		</Class>
 		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
 			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
@@ -1384,166 +680,6 @@
 			<Class name="unsigned int" field="platformFlags" value="255" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 			<Class name="AZStd::string" field="pathHint" value="config/spec/pc_veryhigh.cfg" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{7C8D5984-4282-5A7A-8F1A-128FB539DFB6}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/color_blue.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{31261B2C-C26D-5FB0-BAE2-D26FB2075E70}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/color_cyan.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{A5C4E720-A3C7-5C65-BD8B-DDD9505945FD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/color_green.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{FAB14BE8-A5E6-5B2D-AAC8-E797951A37D4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/color_magenta.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{6054B7C8-859D-50B6-9D0B-5F9BAC91A71C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/color_orange.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{69073C24-F9FC-5B2C-BFD1-983ECC76D9A3}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/color_purple.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{AB3993B7-F89B-5C86-AFF9-452584B99CA5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/color_red.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{DA13AE0E-68E0-5FA3-B335-F3209883B49B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/color_white.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{141C2C7F-AEB2-5121-90D6-807525B168CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/color_yellow.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{7E73949E-1D79-5B3A-B787-4F098344C26A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/mipmapdebug.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{10DCCDD1-60FC-566B-9DE4-936C9DDE01D3}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/replaceme.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{69015F42-750A-53A2-9D10-B4A22D064DE7}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/texturecompiling.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{B2D65572-A209-5222-AAEB-903220636818}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/texturecompiling_a.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{CFED46A4-83E7-5616-B3BB-4BB218927804}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="3000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/texturecompiling_cm_ibldiffuse.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{CFED46A4-83E7-5616-B3BB-4BB218927804}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="2000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/texturecompiling_cm_iblspecular.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{254812AC-7A00-5FEE-B9ED-6E181E1F6408}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/texturecompiling_ddn.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{2873AD02-367D-520B-8D79-58BF25328AF7}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/texturecompiling_ddna.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{6A04254A-BA1A-5392-B5CC-8585CBB189A6}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/greyalpha.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{1213DEB1-FC2B-566A-86AA-E82D93D8AE2F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/materials/lens_optics.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{6E4F82A0-0C23-578B-B68F-C071F136B2AE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/objects/helper.mtl" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
 		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
 			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
 				<Class name="AZ::Uuid" field="guid" value="{A8970A25-5043-5519-A927-F180E7D6E8C1}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
@@ -1632,46 +768,6 @@
 			<Class name="unsigned int" field="platformFlags" value="255" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 			<Class name="AZStd::string" field="pathHint" value="engine_dependencies.xml" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{3B3997AF-DDB9-5E52-877D-90C72F2E53EE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/defaults/16_5.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{099C5359-AEE0-5158-BBFD-36D3E3C552BD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/defaults/16_34.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{AD8E4A1C-BD52-5480-911E-E351EA75DF5B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/textures/defaults/16_12.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{E0C71739-AA65-56B4-8D0D-388C853CAE33}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/notfound.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
-		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
-			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-				<Class name="AZ::Uuid" field="guid" value="{16A565B6-FF97-5C0E-A455-58E0D329DA55}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-				<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			</Class>
-			<Class name="unsigned int" field="platformFlags" value="127" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-			<Class name="AZStd::string" field="pathHint" value="engineassets/texturemsg/notfound_ddna.tif.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		</Class>
 	</Class>
 </ObjectStream>
 

+ 0 - 1
AutomatedTesting/AutomatedTesting_Dependencies.xml

@@ -1,5 +1,4 @@
 <EngineDependencies versionnumber="1.0.0">
     <Dependency path="libs/particles/preloadlibs.txt" optional="true" />
     <Dependency path="libs/gameaudio/wwise/*.xml" optional="false" />
-    <Dependency path=":libs/gameaudio/wwise/levels/default_controls.xml" optional="false" />
 </EngineDependencies>

+ 6 - 4
Code/Framework/AzCore/AzCore/IO/Streamer/Scheduler.cpp

@@ -43,10 +43,12 @@ namespace AZ::IO
 
             m_mainLoopDesc = threadDesc;
             m_mainLoopDesc.m_name = "IO Scheduler";
-            m_mainLoop = AZStd::thread([this]()
-            {
-                Thread_MainLoop();
-            }, &m_mainLoopDesc);
+            m_mainLoop = AZStd::thread(
+                m_mainLoopDesc,
+                [this]()
+                {
+                    Thread_MainLoop();
+                });
         }
     }
 

+ 2 - 2
Code/Framework/AzCore/AzCore/Jobs/Internal/JobManagerWorkStealing.cpp

@@ -644,11 +644,11 @@ JobManagerWorkStealing::ThreadList JobManagerWorkStealing::CreateWorkerThreads(c
         }
 
         info->m_thread = AZStd::thread(
+            threadDesc,
             [this, info]()
             {
                 this->ProcessJobsWorker(info);
-            },
-            &threadDesc
+            }
         );
 
         info->m_threadId = info->m_thread.get_id();

+ 3 - 3
Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp

@@ -205,13 +205,13 @@ namespace AZ
                 }
                 m_active.store(true, AZStd::memory_order_release);
 
-                m_thread = AZStd::thread{ [this, &initSemaphore]
+                m_thread = AZStd::thread{ desc,
+                                          [this, &initSemaphore]
                                           {
                                               t_worker = this;
                                               initSemaphore.release();
                                               Run();
-                                          },
-                                          &desc };
+                                          } };
             }
 
             // Threads that wait on a graph to complete are disqualified from receiving tasks until the wait finishes

+ 11 - 8
Code/Framework/AzCore/AzCore/std/parallel/thread.h

@@ -87,12 +87,6 @@ namespace AZStd
 
         // construct/copy/destroy:
         thread();
-        /**
-         * \note thread_desc is AZStd extension.
-         */
-        template <class F>
-        explicit thread(F&& f, const thread_desc* desc = 0);
-
         ~thread();
 
         thread(thread&& rhs)
@@ -108,6 +102,15 @@ namespace AZStd
             return *this;
         }
 
+        template<class F, class... Args, typename = AZStd::enable_if_t<!AZStd::is_convertible_v<AZStd::decay_t<F>, thread_desc>>>
+        explicit thread(F&& f, Args&&... args);
+
+        /**
+         * \note thread_desc is AZStd extension.
+         */
+        template<class F, class... Args>
+        thread(const thread_desc& desc, F&& f, Args&&... args);
+
         // Till we fully have RVALUES
         template <class F>
         explicit thread(Internal::thread_move_t<F> f);
@@ -138,8 +141,8 @@ namespace AZStd
         //thread(AZStd::delegate<void ()> d,const thread_desc* desc = 0);
         
     private:
-        thread(thread&);
-        thread& operator=(thread&);
+        thread(const thread&) = delete;
+        thread& operator=(const thread&) = delete;
 
         native_thread_data_type     m_thread;
     };

+ 15 - 5
Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/std/parallel/internal/thread_UnixLike.h

@@ -10,6 +10,8 @@
 #include <unistd.h>
 #include <sched.h>
 
+#include <AzCore/std/tuple.h>
+
 namespace AZStd
 {
     namespace Internal
@@ -22,12 +24,20 @@ namespace AZStd
 
     //////////////////////////////////////////////////////////////////////////
     // thread
-    template <class F>
-    inline thread::thread(F&& f, const thread_desc* desc)
+    template<class F, class... Args, typename>
+    thread::thread(F&& f, Args&&... args)
+        : thread(thread_desc{}, AZStd::forward<F>(f), AZStd::forward<Args>(args)...)
+    {}
+
+    template<class F, class... Args>
+    thread::thread(const thread_desc& desc, F&& f, Args&&... args)
     {
-        Internal::thread_info* ti = Internal::create_thread_info(AZStd::forward<F>(f));
-        ti->m_name = desc ? desc->m_name : nullptr;
-        m_thread = Internal::create_thread(desc, ti);
+        auto threadfunc = [fn = AZStd::forward<F>(f), argsTuple = AZStd::make_tuple(AZStd::forward<Args>(args)...)]() mutable -> void
+        {
+            AZStd::apply(AZStd::move(fn), AZStd::move(argsTuple));
+        };
+        Internal::thread_info* ti = Internal::create_thread_info(AZStd::move(threadfunc));
+        m_thread = Internal::create_thread(&desc, ti);
     }
 
     inline bool thread::joinable() const

+ 15 - 4
Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/std/parallel/internal/thread_WinAPI.h

@@ -18,6 +18,8 @@ extern "C"
     AZ_DLL_IMPORT unsigned long __stdcall GetCurrentThreadId(void);
 }
 
+#include <AzCore/std/tuple.h>
+
 namespace AZStd
 {
     namespace Internal
@@ -30,11 +32,20 @@ namespace AZStd
 
     //////////////////////////////////////////////////////////////////////////
     // thread
-    template <class F>
-    inline thread::thread(F&& f, const thread_desc* desc)
+    template<class F, class... Args, typename>
+    thread::thread(F&& f, Args&&... args)
+        : thread(thread_desc{}, AZStd::forward<F>(f), AZStd::forward<Args>(args)...)
+    {}
+
+    template<class F, class... Args>
+    thread::thread(const thread_desc& desc, F&& f, Args&&... args)
     {
-        Internal::thread_info* ti = Internal::create_thread_info(AZStd::forward<F>(f));
-        m_thread.m_handle = Internal::create_thread(desc, ti, &m_thread.m_id);
+        auto threadfunc = [fn = AZStd::forward<F>(f), argsTuple = AZStd::make_tuple(AZStd::forward<Args>(args)...)]() mutable -> void
+        {
+            AZStd::apply(AZStd::move(fn), AZStd::move(argsTuple));
+        };
+        Internal::thread_info* ti = Internal::create_thread_info(AZStd::move(threadfunc));
+        m_thread.m_handle = Internal::create_thread(&desc, ti, &m_thread.m_id);
     }
 
     inline bool thread::joinable() const

+ 77 - 77
Code/Framework/AzCore/Tests/AZStd/Parallel.cpp

@@ -195,18 +195,18 @@ namespace UnitTest
 
         void test_thread_id_for_running_thread_is_not_default_constructed_id()
         {
-            const thread_desc* desc = m_numThreadDesc ? &m_desc[0] : nullptr;
-            AZStd::thread t(AZStd::bind(&Parallel_Thread::do_nothing, this), desc);
+            const thread_desc desc = m_numThreadDesc ? m_desc[0] : thread_desc{};
+            AZStd::thread t(desc, AZStd::bind(&Parallel_Thread::do_nothing, this));
             AZ_TEST_ASSERT(t.get_id() != AZStd::thread::id());
             t.join();
         }
 
         void test_different_threads_have_different_ids()
         {
-            const thread_desc* desc1 = m_numThreadDesc ? &m_desc[0] : nullptr;
-            const thread_desc* desc2 = m_numThreadDesc ? &m_desc[1] : nullptr;
-            AZStd::thread t(AZStd::bind(&Parallel_Thread::do_nothing, this), desc1);
-            AZStd::thread t2(AZStd::bind(&Parallel_Thread::do_nothing, this), desc2);
+            const thread_desc desc1 = m_numThreadDesc ? m_desc[0] : thread_desc{};
+            const thread_desc desc2 = m_numThreadDesc ? m_desc[1] : thread_desc{};
+            AZStd::thread t(desc1, AZStd::bind(&Parallel_Thread::do_nothing, this));
+            AZStd::thread t2(desc2, AZStd::bind(&Parallel_Thread::do_nothing, this));
             AZ_TEST_ASSERT(t.get_id() != t2.get_id());
             t.join();
             t2.join();
@@ -214,13 +214,13 @@ namespace UnitTest
 
         void test_thread_ids_have_a_total_order()
         {
-            const thread_desc* desc1 = m_numThreadDesc ? &m_desc[0] : nullptr;
-            const thread_desc* desc2 = m_numThreadDesc ? &m_desc[1] : nullptr;
-            const thread_desc* desc3 = m_numThreadDesc ? &m_desc[2] : nullptr;
+            const thread_desc desc1 = m_numThreadDesc ? m_desc[0] : thread_desc{};
+            const thread_desc desc2 = m_numThreadDesc ? m_desc[1] : thread_desc{};
+            const thread_desc desc3 = m_numThreadDesc ? m_desc[2] : thread_desc{};
 
-            AZStd::thread t(AZStd::bind(&Parallel_Thread::do_nothing, this), desc1);
-            AZStd::thread t2(AZStd::bind(&Parallel_Thread::do_nothing, this), desc2);
-            AZStd::thread t3(AZStd::bind(&Parallel_Thread::do_nothing, this), desc3);
+            AZStd::thread t(desc1, AZStd::bind(&Parallel_Thread::do_nothing, this));
+            AZStd::thread t2(desc2, AZStd::bind(&Parallel_Thread::do_nothing, this));
+            AZStd::thread t3(desc3, AZStd::bind(&Parallel_Thread::do_nothing, this));
             AZ_TEST_ASSERT(t.get_id() != t2.get_id());
             AZ_TEST_ASSERT(t.get_id() != t3.get_id());
             AZ_TEST_ASSERT(t2.get_id() != t3.get_id());
@@ -313,10 +313,10 @@ namespace UnitTest
 
         void test_thread_id_of_running_thread_returned_by_this_thread_get_id()
         {
-            const thread_desc* desc1 = m_numThreadDesc ? &m_desc[0] : nullptr;
+            const thread_desc desc1 = m_numThreadDesc ? m_desc[0] : thread_desc{};
 
             AZStd::thread::id id;
-            AZStd::thread t(AZStd::bind(&Parallel_Thread::get_thread_id, this, &id), desc1);
+            AZStd::thread t(desc1, AZStd::bind(&Parallel_Thread::get_thread_id, this, &id));
             AZStd::thread::id t_id = t.get_id();
             t.join();
             AZ_TEST_ASSERT(id == t_id);
@@ -366,10 +366,10 @@ namespace UnitTest
 
         void test_move_on_construction()
         {
-            const thread_desc* desc1 = m_numThreadDesc ? &m_desc[0] : nullptr;
+            const thread_desc desc1 = m_numThreadDesc ? m_desc[0] : thread_desc{};
             AZStd::thread::id the_id;
             AZStd::thread x;
-            x = AZStd::thread(AZStd::bind(&Parallel_Thread::do_nothing_id, this, &the_id), desc1);
+            x = AZStd::thread(desc1, AZStd::bind(&Parallel_Thread::do_nothing_id, this, &the_id));
             AZStd::thread::id x_id = x.get_id();
             x.join();
             AZ_TEST_ASSERT(the_id == x_id);
@@ -377,8 +377,8 @@ namespace UnitTest
 
         AZStd::thread make_thread(AZStd::thread::id* the_id)
         {
-            const thread_desc* desc1 = m_numThreadDesc ? &m_desc[0] : nullptr;
-            return AZStd::thread(AZStd::bind(&Parallel_Thread::do_nothing_id, this, the_id), desc1);
+            const thread_desc desc1 = m_numThreadDesc ? m_desc[0] : thread_desc{};
+            return AZStd::thread(desc1, AZStd::bind(&Parallel_Thread::do_nothing_id, this, the_id));
         }
 
         void test_move_from_function_return()
@@ -430,9 +430,9 @@ namespace UnitTest
 
         void do_test_creation()
         {
-            const thread_desc* desc1 = m_numThreadDesc ? &m_desc[0] : nullptr;
+            const thread_desc desc1 = m_numThreadDesc ? m_desc[0] : thread_desc{};
             m_data = 0;
-            AZStd::thread t(AZStd::bind(&Parallel_Thread::simple_thread, this), desc1);
+            AZStd::thread t(desc1, AZStd::bind(&Parallel_Thread::simple_thread, this));
             t.join();
             AZ_TEST_ASSERT(m_data == 999);
         }
@@ -445,9 +445,9 @@ namespace UnitTest
 
         void do_test_id_comparison()
         {
-            const thread_desc* desc1 = m_numThreadDesc ? &m_desc[0] : nullptr;
+            const thread_desc desc1 = m_numThreadDesc ? m_desc[0] : thread_desc{};
             AZStd::thread::id self = this_thread::get_id();
-            AZStd::thread thrd(AZStd::bind(&Parallel_Thread::comparison_thread, this, self), desc1);
+            AZStd::thread thrd(desc1, AZStd::bind(&Parallel_Thread::comparison_thread, this, self));
             thrd.join();
         }
 
@@ -476,10 +476,10 @@ namespace UnitTest
 
         void do_test_creation_through_reference_wrapper()
         {
-            const thread_desc* desc1 = m_numThreadDesc ? &m_desc[0] : nullptr;
+            const thread_desc desc1 = m_numThreadDesc ? m_desc[0] : thread_desc{};
             non_copyable_functor f;
 
-            AZStd::thread thrd(AZStd::ref(f), desc1);
+            AZStd::thread thrd(desc1, AZStd::ref(f));
             thrd.join();
             AZ_TEST_ASSERT(f.value == 999);
         }
@@ -491,10 +491,10 @@ namespace UnitTest
 
         void test_swap()
         {
-            const thread_desc* desc1 = m_numThreadDesc ? &m_desc[0] : nullptr;
-            const thread_desc* desc2 = m_numThreadDesc ? &m_desc[1] : nullptr;
-            AZStd::thread t(AZStd::bind(&Parallel_Thread::simple_thread, this), desc1);
-            AZStd::thread t2(AZStd::bind(&Parallel_Thread::simple_thread, this), desc2);
+            const thread_desc desc1 = m_numThreadDesc ? m_desc[0] : thread_desc{};
+            const thread_desc desc2 = m_numThreadDesc ? m_desc[1] : thread_desc{};
+            AZStd::thread t(desc1, AZStd::bind(&Parallel_Thread::simple_thread, this));
+            AZStd::thread t2(desc2, AZStd::bind(&Parallel_Thread::simple_thread, this));
             AZStd::thread::id id1 = t.get_id();
             AZStd::thread::id id2 = t2.get_id();
 
@@ -512,7 +512,7 @@ namespace UnitTest
 
         void run()
         {
-            const thread_desc* desc1 = m_numThreadDesc ? &m_desc[0] : nullptr;
+            const thread_desc desc1 = m_numThreadDesc ? m_desc[0] : thread_desc{};
 
             // We need to have at least one processor
             AZ_TEST_ASSERT(AZStd::thread::hardware_concurrency() >= 1);
@@ -520,18 +520,18 @@ namespace UnitTest
             // Create thread to increment data till we need to
             m_data = 0;
             m_dataMax = 10;
-            AZStd::thread tr(AZStd::bind(&Parallel_Thread::increment_data, this), desc1);
+            AZStd::thread tr(desc1, AZStd::bind(&Parallel_Thread::increment_data, this));
             tr.join();
             AZ_TEST_ASSERT(m_data == m_dataMax);
 
             m_data = 0;
-            AZStd::thread trDel(make_delegate(this, &Parallel_Thread::increment_data), desc1);
+            AZStd::thread trDel(desc1, make_delegate(this, &Parallel_Thread::increment_data));
             trDel.join();
             AZ_TEST_ASSERT(m_data == m_dataMax);
 
             chrono::system_clock::time_point startTime = chrono::system_clock::now();
             {
-                AZStd::thread tr1(AZStd::bind(&Parallel_Thread::sleep_thread, this, chrono::milliseconds(100)), desc1);
+                AZStd::thread tr1(desc1, AZStd::bind(&Parallel_Thread::sleep_thread, this, chrono::milliseconds(100)));
                 tr1.join();
             }
             auto sleepTime = chrono::system_clock::now() - startTime;
@@ -563,71 +563,71 @@ namespace UnitTest
             {
                 MfTest x;
                 AZStd::function<void ()> func = AZStd::bind(&MfTest::f0, &x);
-                AZStd::thread(func, desc1).join();
+                AZStd::thread(desc1, func).join();
                 func = AZStd::bind(&MfTest::f0, AZStd::ref(x));
-                AZStd::thread(func, desc1).join();
+                AZStd::thread(desc1, func).join();
                 func = AZStd::bind(&MfTest::g0, &x);
-                AZStd::thread(func, desc1).join();
+                AZStd::thread(desc1, func).join();
                 func = AZStd::bind(&MfTest::g0, x);
-                AZStd::thread(func, desc1).join();
+                AZStd::thread(desc1, func).join();
                 func = AZStd::bind(&MfTest::g0, AZStd::ref(x));
-                AZStd::thread(func, desc1).join();
+                AZStd::thread(desc1, func).join();
 
                 //// 1
-                //thread( AZStd::bind(&MfTest::f1, &x, 1) , desc1).join();
-                //thread( AZStd::bind(&MfTest::f1, AZStd::ref(x), 1) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g1, &x, 1) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g1, x, 1) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g1, AZStd::ref(x), 1) , desc1).join();
+                //thread( AZStd::bind(desc1, &MfTest::f1, &x, 1)).join();
+                //thread( AZStd::bind(desc1, &MfTest::f1, AZStd::ref(x), 1)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g1, &x, 1)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g1, x, 1)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g1, AZStd::ref(x), 1)).join();
 
                 //// 2
-                //thread( AZStd::bind(&MfTest::f2, &x, 1, 2) , desc1).join();
-                //thread( AZStd::bind(&MfTest::f2, AZStd::ref(x), 1, 2) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g2, &x, 1, 2) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g2, x, 1, 2) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g2, AZStd::ref(x), 1, 2) , desc1).join();
+                //thread( AZStd::bind(desc1, &MfTest::f2, &x, 1, 2)).join();
+                //thread( AZStd::bind(desc1, &MfTest::f2, AZStd::ref(x), 1, 2)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g2, &x, 1, 2)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g2, x, 1, 2)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g2, AZStd::ref(x), 1, 2)).join();
 
                 //// 3
-                //thread( AZStd::bind(&MfTest::f3, &x, 1, 2, 3) , desc1).join();
-                //thread( AZStd::bind(&MfTest::f3, AZStd::ref(x), 1, 2, 3) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g3, &x, 1, 2, 3) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g3, x, 1, 2, 3) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g3, AZStd::ref(x), 1, 2, 3) , desc1).join();
+                //thread( AZStd::bind(desc1, &MfTest::f3, &x, 1, 2, 3)).join();
+                //thread( AZStd::bind(desc1, &MfTest::f3, AZStd::ref(x), 1, 2, 3)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g3, &x, 1, 2, 3)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g3, x, 1, 2, 3)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g3, AZStd::ref(x), 1, 2, 3)).join();
 
                 //// 4
-                //thread( AZStd::bind(&MfTest::f4, &x, 1, 2, 3, 4) , desc1).join();
-                //thread( AZStd::bind(&MfTest::f4, AZStd::ref(x), 1, 2, 3, 4) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g4, &x, 1, 2, 3, 4) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g4, x, 1, 2, 3, 4) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g4, AZStd::ref(x), 1, 2, 3, 4) , desc1).join();
+                //thread( AZStd::bind(desc1, &MfTest::f4, &x, 1, 2, 3, 4)).join();
+                //thread( AZStd::bind(desc1, &MfTest::f4, AZStd::ref(x), 1, 2, 3, 4)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g4, &x, 1, 2, 3, 4)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g4, x, 1, 2, 3, 4)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g4, AZStd::ref(x), 1, 2, 3, 4)).join();
 
                 //// 5
-                //thread( AZStd::bind(&MfTest::f5, &x, 1, 2, 3, 4, 5) , desc1).join();
-                //thread( AZStd::bind(&MfTest::f5, AZStd::ref(x), 1, 2, 3, 4, 5) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g5, &x, 1, 2, 3, 4, 5) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g5, x, 1, 2, 3, 4, 5) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g5, AZStd::ref(x), 1, 2, 3, 4, 5) , desc1).join();
+                //thread( AZStd::bind(desc1, &MfTest::f5, &x, 1, 2, 3, 4, 5)).join();
+                //thread( AZStd::bind(desc1, &MfTest::f5, AZStd::ref(x), 1, 2, 3, 4, 5)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g5, &x, 1, 2, 3, 4, 5)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g5, x, 1, 2, 3, 4, 5)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g5, AZStd::ref(x), 1, 2, 3, 4, 5)).join();
 
                 //// 6
-                //thread( AZStd::bind(&MfTest::f6, &x, 1, 2, 3, 4, 5, 6) , desc1).join();
-                //thread( AZStd::bind(&MfTest::f6, AZStd::ref(x), 1, 2, 3, 4, 5, 6) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g6, &x, 1, 2, 3, 4, 5, 6) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g6, x, 1, 2, 3, 4, 5, 6) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g6, AZStd::ref(x), 1, 2, 3, 4, 5, 6) , desc1).join();
+                //thread( AZStd::bind(desc1, &MfTest::f6, &x, 1, 2, 3, 4, 5, 6)).join();
+                //thread( AZStd::bind(desc1, &MfTest::f6, AZStd::ref(x), 1, 2, 3, 4, 5, 6)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g6, &x, 1, 2, 3, 4, 5, 6)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g6, x, 1, 2, 3, 4, 5, 6)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g6, AZStd::ref(x), 1, 2, 3, 4, 5, 6)).join();
 
                 //// 7
-                //thread( AZStd::bind(&MfTest::f7, &x, 1, 2, 3, 4, 5, 6, 7), desc1).join();
-                //thread( AZStd::bind(&MfTest::f7, AZStd::ref(x), 1, 2, 3, 4, 5, 6, 7), desc1).join();
-                //thread( AZStd::bind(&MfTest::g7, &x, 1, 2, 3, 4, 5, 6, 7), desc1).join();
-                //thread( AZStd::bind(&MfTest::g7, x, 1, 2, 3, 4, 5, 6, 7), desc1).join();
-                //thread( AZStd::bind(&MfTest::g7, AZStd::ref(x), 1, 2, 3, 4, 5, 6, 7), desc1).join();
+                //thread( AZStd::bind(desc1, &MfTest::f7, &x, 1, 2, 3, 4, 5, 6, 7)).join();
+                //thread( AZStd::bind(desc1, &MfTest::f7, AZStd::ref(x), 1, 2, 3, 4, 5, 6, 7)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g7, &x, 1, 2, 3, 4, 5, 6, 7)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g7, x, 1, 2, 3, 4, 5, 6, 7)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g7, AZStd::ref(x), 1, 2, 3, 4, 5, 6, 7)).join();
 
                 //// 8
-                //thread( AZStd::bind(&MfTest::f8, &x, 1, 2, 3, 4, 5, 6, 7, 8) , desc1).join();
-                //thread( AZStd::bind(&MfTest::f8, AZStd::ref(x), 1, 2, 3, 4, 5, 6, 7, 8) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g8, &x, 1, 2, 3, 4, 5, 6, 7, 8) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g8, x, 1, 2, 3, 4, 5, 6, 7, 8) , desc1).join();
-                //thread( AZStd::bind(&MfTest::g8, AZStd::ref(x), 1, 2, 3, 4, 5, 6, 7, 8) , desc1).join();
+                //thread( AZStd::bind(desc1, &MfTest::f8, &x, 1, 2, 3, 4, 5, 6, 7, 8)).join();
+                //thread( AZStd::bind(desc1, &MfTest::f8, AZStd::ref(x), 1, 2, 3, 4, 5, 6, 7, 8)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g8, &x, 1, 2, 3, 4, 5, 6, 7, 8)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g8, x, 1, 2, 3, 4, 5, 6, 7, 8)).join();
+                //thread( AZStd::bind(desc1, &MfTest::g8, AZStd::ref(x), 1, 2, 3, 4, 5, 6, 7, 8)).join();
 
                 AZ_TEST_ASSERT(x.m_hash == 1366);
             }

+ 5 - 5
Code/Framework/AzCore/Tests/Memory.cpp

@@ -151,7 +151,7 @@ namespace UnitTest
                     AZStd::thread m_threads[m_maxNumThreads];
                     for (unsigned int i = 0; i < m_maxNumThreads; ++i)
                     {
-                        m_threads[i] = AZStd::thread(AZStd::bind(&SystemAllocatorTest::ThreadFunc, this), &m_desc[i]);
+                        m_threads[i] = AZStd::thread(m_desc[i], AZStd::bind(&SystemAllocatorTest::ThreadFunc, this));
                         // give some time offset to the threads so we can test alloc and dealloc at the same time.
                         //AZStd::this_thread::sleep_for(AZStd::chrono::microseconds(500));
                     }
@@ -286,7 +286,7 @@ namespace UnitTest
                 AZStd::thread m_threads[m_maxNumThreads];
                 for (unsigned int i = 0; i < m_maxNumThreads; ++i)
                 {
-                    m_threads[i] = AZStd::thread(AZStd::bind(&SystemAllocatorTest::ThreadFunc, this), &m_desc[i]);
+                    m_threads[i] = AZStd::thread(m_desc[i], AZStd::bind(&SystemAllocatorTest::ThreadFunc, this));
                     // give some time offset to the threads so we can test alloc and dealloc at the same time.
                     AZStd::this_thread::sleep_for(AZStd::chrono::microseconds(500));
                 }
@@ -724,7 +724,7 @@ namespace UnitTest
                 AZStd::thread m_threads[m_maxNumThreads];
                 for (unsigned int i = 0; i < m_maxNumThreads; ++i)
                 {
-                    m_threads[i] = AZStd::thread(AZStd::bind(&ThreadPoolAllocatorTest::AllocDeallocFunc, this), &m_desc[i]);
+                    m_threads[i] = AZStd::thread(m_desc[i], AZStd::bind(&ThreadPoolAllocatorTest::AllocDeallocFunc, this));
                 }
 
                 for (unsigned int i = 0; i < m_maxNumThreads; ++i)
@@ -743,12 +743,12 @@ namespace UnitTest
 
                 for (unsigned int i = m_maxNumThreads/2; i <m_maxNumThreads; ++i)
                 {
-                    m_threads[i] = AZStd::thread(AZStd::bind(&ThreadPoolAllocatorTest::SharedDeAlloc, this), &m_desc[i]);
+                    m_threads[i] = AZStd::thread(m_desc[i], AZStd::bind(&ThreadPoolAllocatorTest::SharedDeAlloc, this));
                 }
 
                 for (unsigned int i = 0; i < m_maxNumThreads/2; ++i)
                 {
-                    m_threads[i] = AZStd::thread(AZStd::bind(&ThreadPoolAllocatorTest::SharedAlloc, this), &m_desc[i]);
+                    m_threads[i] = AZStd::thread(m_desc[i], AZStd::bind(&ThreadPoolAllocatorTest::SharedAlloc, this));
                 }
 
                 for (unsigned int i = 0; i < m_maxNumThreads/2; ++i)

+ 9 - 7
Code/Framework/AzFramework/AzFramework/Application/Application.cpp

@@ -479,14 +479,16 @@ namespace AzFramework
         newThreadDesc.m_cpuId = AFFINITY_MASK_USERTHREADS;
         newThreadDesc.m_name = newThreadName;
         AZStd::binary_semaphore binarySemaphore;
-        AZStd::thread newThread([&workForNewThread, &binarySemaphore, &newThreadName]
-        {
-            AZ_PROFILE_SCOPE(AzFramework,
-                "Application::PumpSystemEventLoopWhileDoingWorkInNewThread:ThreadWorker %s", newThreadName);
+        AZStd::thread newThread(
+            newThreadDesc,
+            [&workForNewThread, &binarySemaphore, &newThreadName]
+            {
+                AZ_PROFILE_SCOPE(AzFramework,
+                    "Application::PumpSystemEventLoopWhileDoingWorkInNewThread:ThreadWorker %s", newThreadName);
 
-            workForNewThread();
-            binarySemaphore.release();
-        }, &newThreadDesc);
+                workForNewThread();
+                binarySemaphore.release();
+            });
         while (!binarySemaphore.try_acquire_for(eventPumpFrequency))
         {
             PumpSystemEventLoopUntilEmpty();

+ 14 - 1
Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp

@@ -1631,7 +1631,20 @@ namespace AZ::IO
             return nullptr;
         }
 
-        ZipDir::CacheFactory factory(ZipDir::ZD_INIT_FAST, nFactoryFlags);
+        ZipDir::InitMethod initType = ZipDir::InitMethod::Default;
+        if (!ZipDir::IsReleaseConfig)
+        {
+            if ((nFlags & INestedArchive::FLAGS_FULL_VALIDATE) != 0)
+            {
+                initType = ZipDir::InitMethod::FullValidation;
+            }
+            else if ((nFlags & INestedArchive::FLAGS_VALIDATE_HEADERS) != 0)
+            {
+                initType = ZipDir::InitMethod::ValidateHeaders;
+            }
+        }
+
+        ZipDir::CacheFactory factory(initType, nFactoryFlags);
 
         ZipDir::CachePtr cache = factory.New(szFullPath->c_str());
         if (cache)

+ 13 - 0
Code/Framework/AzFramework/AzFramework/Archive/INestedArchive.h

@@ -11,7 +11,9 @@
 
 #include <AzCore/IO/Path/Path_fwd.h>
 #include <AzCore/Math/Crc.h>
+#include <AzCore/std/containers/vector.h>
 #include <AzCore/std/smart_ptr/intrusive_base.h>
+#include <AzCore/std/string/string.h>
 #include <AzFramework/Archive/Codec.h>
 
 namespace AZ::IO
@@ -71,6 +73,13 @@ namespace AZ::IO
             // multiple times
             FLAGS_DONT_COMPACT = 1 << 5,
 
+            // if this is set, validate header data when opening the archive
+            FLAGS_VALIDATE_HEADERS = 1 << 9,
+
+            // if this is set, validate header data when opening the archive and validate CRCs when decompressing
+            // & reading files.
+            FLAGS_FULL_VALIDATE = 1 << 10,
+
             // Disable a pak file without unloading it, this flag is used in combination with patches and multiplayer
             // to ensure that specific paks stay in the position(to keep the same priority) but being disabled
             // when running multiplayer
@@ -128,6 +137,10 @@ namespace AZ::IO
         //   Deletes all files and directories in the archive.
         virtual int RemoveAll() = 0;
 
+        // Summary:
+        //   Lists all the files in the archive.
+        virtual int ListAllFiles(AZStd::vector<AZ::IO::Path>& outFileEntries) = 0;
+
         // Summary:
         //   Finds the file; you don't have to close the returned handle.
         // Returns:

+ 40 - 0
Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.cpp

@@ -89,11 +89,51 @@ namespace AZ::IO
         return m_pCache->RemoveDir(fullPath);
     }
 
+    //////////////////////////////////////////////////////////////////////////
     int NestedArchive::RemoveAll()
     {
         return m_pCache->RemoveAll();
     }
 
+    //////////////////////////////////////////////////////////////////////////
+    // Helper for 'ListAllFiles' to recursively traverse the FileEntryTree and gather all the files
+    void EnumerateFilesRecursive(AZ::IO::Path currentPath, ZipDir::FileEntryTree* currentTree, AZStd::vector<AZ::IO::Path>& fileList)
+    {
+        // Drill down directories first...
+        for (auto dirIter = currentTree->GetDirBegin(); dirIter != currentTree->GetDirEnd(); ++dirIter)
+        {
+            if (ZipDir::FileEntryTree* subTree = currentTree->GetDirEntry(dirIter);
+                subTree != nullptr)
+            {
+                EnumerateFilesRecursive(currentPath / currentTree->GetDirName(dirIter), subTree, fileList);
+            }
+        }
+
+        // Then enumerate the files in current directory...
+        for (auto fileIter = currentTree->GetFileBegin(); fileIter != currentTree->GetFileEnd(); ++fileIter)
+        {
+            fileList.emplace_back(currentPath / currentTree->GetFileName(fileIter));
+        }
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+    // lists all files in the archive
+    int NestedArchive::ListAllFiles(AZStd::vector<AZ::IO::Path>& outFileEntries)
+    {
+        AZStd::vector<AZ::IO::Path> filesInArchive;
+
+        ZipDir::FileEntryTree* tree = m_pCache->GetRoot();
+        if (!tree)
+        {
+            return ZipDir::ZD_ERROR_UNEXPECTED;
+        }
+
+        EnumerateFilesRecursive(AZ::IO::Path{ AZ::IO::PosixPathSeparator }, tree, filesInArchive);
+
+        AZStd::swap(outFileEntries, filesInArchive);
+        return ZipDir::ZD_ERROR_SUCCESS;
+    }
+
     //////////////////////////////////////////////////////////////////////////
     // Adds a new file to the zip or update an existing one
     // adds a directory (creates several nested directories if needed)

+ 7 - 2
Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.h

@@ -39,7 +39,7 @@ namespace AZ::IO
 
         NestedArchive(IArchive* pArchive, AZStd::string_view strBindRoot, ZipDir::CachePtr pCache, uint32_t nFlags = 0);
         ~NestedArchive() override;
-        
+
         auto GetRootFolderHandle() -> Handle override;
 
         // Adds a new file to the zip or update an existing one
@@ -68,6 +68,9 @@ namespace AZ::IO
         // deletes all files from the archive
         int RemoveAll() override;
 
+        // lists all the files in the archive
+        int ListAllFiles(AZStd::vector<AZ::IO::Path>& outFileEntries) override;
+
         // finds the file; you don't have to close the returned handle
         Handle FindFile(AZStd::string_view szRelativePath) override;
 
@@ -79,7 +82,6 @@ namespace AZ::IO
 
         // returns the full path to the archive file
         AZ::IO::PathView GetFullPath() const override;
-        ZipDir::Cache* GetCache();
 
         uint32_t GetFlags() const override;
         bool SetFlags(uint32_t nFlagsToSet) override;
@@ -87,12 +89,15 @@ namespace AZ::IO
 
         bool SetPackAccessible(bool bAccessible) override;
 
+        ZipDir::Cache* GetCache();
+
     protected:
         // returns the pointer to the relative file path to be passed
         // to the underlying Cache pointer. Uses the given buffer to construct the path.
         // returns nullptr if the file path is invalid
         AZ::IO::FixedMaxPathString AdjustPath(AZStd::string_view szRelativePath);
 
+
         ZipDir::CachePtr m_pCache;
         // the binding root may be empty string - in this case, the absolute path binding won't work
         AZ::IO::Path m_strBindRoot;

+ 12 - 1
Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp

@@ -101,10 +101,11 @@ namespace AZ::IO::ZipDir
         FileEntry* operator -> () { return m_pFileEntry; }
         FileEntryTransactionAdd(Cache* pCache, AZStd::string_view szRelativePath)
             : m_pCache(pCache)
+            , m_szRelativePath(AZ::IO::PosixPathSeparator)
             , m_bCommitted(false)
         {
             // Update the cache string pool with the relative path to the file
-            auto pathIt = m_pCache->m_relativePathPool.emplace(AZ::IO::PathView(szRelativePath).LexicallyNormal());
+            auto pathIt = m_pCache->m_relativePathPool.emplace(AZ::IO::PathView(szRelativePath, AZ::IO::PosixPathSeparator).LexicallyNormal());
             m_szRelativePath = *pathIt.first;
             // this is the name of the directory - create it or find it
             m_pFileEntry = m_pCache->GetRoot()->Add(m_szRelativePath.Native());
@@ -740,6 +741,16 @@ namespace AZ::IO::ZipDir
                 {
                     return ZD_ERROR_CORRUPTED_DATA;
                 }
+                if (pFileEntry->bCheckCRCNextRead)
+                {
+                    pFileEntry->bCheckCRCNextRead = false;
+                    uLong uCRC32 = AZ::Crc32((Bytef*)pUncompressed, nSizeUncompressed);
+                    if (uCRC32 != pFileEntry->desc.lCRC32)
+                    {
+                        AZ_Warning("Archive", false, "ZD_ERROR_CRC32_CHECK: Uncompressed stream CRC32 check failed");
+                        return ZD_ERROR_CRC32_CHECK;
+                    }
+                }
             }
         }
 

+ 64 - 138
Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.cpp

@@ -29,7 +29,7 @@ namespace AZ::IO::ZipDir
     // this sets the window size of the blocks of data read from the end of the file to find the Central Directory Record
     // since normally there are no
     static constexpr size_t CDRSearchWindowSize = 0x100;
-    CacheFactory::CacheFactory(InitMethodEnum nInitMethod, uint32_t nFlags)
+    CacheFactory::CacheFactory(InitMethod nInitMethod, uint32_t nFlags)
     {
         m_nCDREndPos = 0;
         m_bBuildFileEntryMap = false; // we only need it for validation/debugging
@@ -448,7 +448,6 @@ namespace AZ::IO::ZipDir
     // builds up the m_mapFileEntries
     bool CacheFactory::BuildFileEntryMap()
     {
-
         Seek(m_CDREnd.lCDROffset);
 
         if (m_CDREnd.lCDRSize == 0)
@@ -530,14 +529,6 @@ namespace AZ::IO::ZipDir
             {
                 // Add this file entry.
                 char* str = reinterpret_cast<char*>(pFileName);
-                for (int i = 0; i < pFile->nFileNameLength; i++)
-                {
-                    str[i] = std::tolower(str[i], std::locale());
-                    if (str[i] == AZ_WRONG_FILESYSTEM_SEPARATOR)
-                    {
-                        str[i] = AZ_CORRECT_FILESYSTEM_SEPARATOR;
-                    }
-                }
                 str[pFile->nFileNameLength] = 0; // Not standard!, may overwrite signature of the next memory record data in zip.
                 AddFileEntry(str, pFile, extra);
             }
@@ -574,11 +565,7 @@ namespace AZ::IO::ZipDir
 
         FileEntryBase fileEntry(*pFileHeader, extra);
 
-        // when using encrypted headers we should always initialize data offsets from CDR
-        if ((m_encryptedHeaders != ZipFile::HEADERS_NOT_ENCRYPTED || m_nInitMethod >= ZD_INIT_FULL) && pFileHeader->desc.lSizeCompressed)
-        {
-            InitDataOffset(fileEntry, pFileHeader);
-        }
+        InitDataOffset(fileEntry, pFileHeader);
 
         if (m_bBuildFileEntryMap)
         {
@@ -606,142 +593,81 @@ namespace AZ::IO::ZipDir
         {
             Seek(pFileHeader->lLocalHeaderOffset);
 
-            // read the local file header and the name (for validation) into the buffer
-            AZStd::vector<char>pBuffer;
-            uint32_t nBufferLength = sizeof(ZipFile::LocalFileHeader) + pFileHeader->nFileNameLength;
-            pBuffer.resize(nBufferLength);
-            Read(&pBuffer[0], nBufferLength);
-
-            // validate the local file header (compare with the CDR file header - they should contain basically the same information)
-            const auto* pLocalFileHeader = reinterpret_cast<const ZipFile::LocalFileHeader*>(&pBuffer[0]);
-            if (pFileHeader->desc != pLocalFileHeader->desc
-                || pFileHeader->nMethod != pLocalFileHeader->nMethod
-                || pFileHeader->nFileNameLength != pLocalFileHeader->nFileNameLength
-                // for a tough validation, we can compare the timestamps of the local and central directory entries
-                // but we won't do that for backward compatibility with ZipDir
-                //|| pFileHeader->nLastModDate != pLocalFileHeader->nLastModDate
-                //|| pFileHeader->nLastModTime != pLocalFileHeader->nLastModTime
-                )
-            {
-                AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED:"
-                    " The local file header descriptor doesn't match the basic parameters declared in the global file header in the file."
-                    " The archive content is misconsistent and may be damaged. Please try to repair the archive");
-                return;
-            }
+            // Read only the LocalFileHeader w/ no additional bytes ('name' or 'extra' fields)
+            AZStd::vector<char> buffer;
+            uint32_t bufferLen = sizeof(ZipFile::LocalFileHeader);
+            buffer.resize_no_construct(bufferLen);
+            Read(buffer.data(), bufferLen);
 
-            // now compare the local file name with the one recorded in CDR: they must match.
-            auto CompareNoCase = [](const char lhs, const char rhs) { return std::tolower(lhs, std::locale()) == std::tolower(rhs, std::locale()); };
-            auto zipFileDataBegin = pBuffer.begin() + sizeof(ZipFile::LocalFileHeader);
-            auto zipFileDataEnd = zipFileDataBegin + pFileHeader->nFileNameLength;
-            if (!AZStd::equal(zipFileDataBegin, zipFileDataEnd, reinterpret_cast<const char*>(pFileHeader + 1), CompareNoCase))
-            {
-                // either file name, or the extra field do not match
-                AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED:"
-                    " The local file header contains file name which does not match the file name of the global file header."
-                    " The archive content is misconsistent with its directory. Please repair the archive");
-                return;
-            }
+            const auto* localFileHeader = reinterpret_cast<const ZipFile::LocalFileHeader*>(buffer.data());
 
-            fileEntry.nFileDataOffset = pFileHeader->lLocalHeaderOffset + sizeof(ZipFile::LocalFileHeader) + pLocalFileHeader->nFileNameLength + pLocalFileHeader->nExtraFieldLength;
-        }
+            // set the correct file data offset...
+            fileEntry.nFileDataOffset = pFileHeader->lLocalHeaderOffset + sizeof(ZipFile::LocalFileHeader) +
+                localFileHeader->nFileNameLength + localFileHeader->nExtraFieldLength;
 
-        // make sure it's the same file and the fileEntry structure is properly initialized
-        AZ_Assert(fileEntry.nFileHeaderOffset == pFileHeader->lLocalHeaderOffset, "The file entry header offset doesn't match the file header local offst");
-
-        fileEntry.nEOFOffset = fileEntry.nFileDataOffset + fileEntry.desc.lSizeCompressed;
-
-        if (fileEntry.nFileDataOffset >= m_nCDREndPos)
-        {
-            AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED:"
-                " The global file header declares the file which crosses the boundaries of the archive."
-                " The archive is either corrupted or truncated, please try to repair it");
-            return;
-        }
+            fileEntry.nEOFOffset = fileEntry.nFileDataOffset + fileEntry.desc.lSizeCompressed;
 
-        if (m_nInitMethod >= ZD_INIT_VALIDATE)
-        {
-            Validate(fileEntry);
-        }
-    }
+            if (m_nInitMethod != ZipDir::InitMethod::Default)
+            {
+                if (m_nInitMethod == ZipDir::InitMethod::FullValidation)
+                {
+                    // Mark the FileEntry to check CRC when the next read occurs
+                    fileEntry.bCheckCRCNextRead = true;
+                }
 
-    //////////////////////////////////////////////////////////////////////////
-    // reads the file pointed by the given header and entry (they must be coherent)
-    // and decompresses it; then calculates and validates its CRC32
-    void CacheFactory::Validate(const FileEntryBase& fileEntry)
-    {
-        AZStd::vector<char> pBuffer;
-        // validate the file contents
-        // allocate memory for both the compressed data and uncompressed data
-        pBuffer.resize(fileEntry.desc.lSizeCompressed + fileEntry.desc.lSizeUncompressed);
-        char* pUncompressed = &pBuffer[fileEntry.desc.lSizeCompressed];
-        char* pCompressed = &pBuffer[0];
+                // Timestamps
+                if (pFileHeader->nLastModDate != localFileHeader->nLastModDate
+                    || pFileHeader->nLastModTime != localFileHeader->nLastModTime)
+                {
+                    AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED: (%s)\n"
+                        " The local file header's modification timestamps don't match that of the global file header in the archive."
+                        " The archive timestamps are inconsistent and may be damaged. Check the archive file.", m_szFilename.c_str());
+                    // don't return here, it may be ok.
+                }
 
-        AZ_Assert(fileEntry.nFileDataOffset != FileEntry::INVALID_DATA_OFFSET, "File entry has invalid data offset of %" PRIx32, FileEntry::INVALID_DATA_OFFSET);
-        Seek(fileEntry.nFileDataOffset);
+                // Validate data
+                if (pFileHeader->desc != localFileHeader->desc  // this checks CRCs and compressed/uncompressed sizes
+                    || pFileHeader->nMethod != localFileHeader->nMethod
+                    || pFileHeader->nFileNameLength != localFileHeader->nFileNameLength)
+                {
+                    AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED: (%s)\n"
+                        " The local file header descriptor doesn't match basic parameters declared in the global file header in the file."
+                        " The archive content is inconsistent and may be damaged. Please try to repair the archive.", m_szFilename.c_str());
+                    // return here because further checks aren't worse than this.
+                    return;
+                }
 
-        Read(pCompressed, fileEntry.desc.lSizeCompressed);
+                // Read extra data
+                uint32_t extraDataLen = localFileHeader->nFileNameLength + localFileHeader->nExtraFieldLength;
+                buffer.resize_no_construct(buffer.size() + extraDataLen);
+                Read(buffer.data() + buffer.size(), extraDataLen);
 
-        size_t nDestSize = fileEntry.desc.lSizeUncompressed;
-        int nError = Z_OK;
-        if (fileEntry.nMethod)
-        {
-            nError = ZipRawUncompress(pUncompressed, &nDestSize, pCompressed, fileEntry.desc.lSizeCompressed);
-        }
-        else
-        {
-            AZ_Assert(fileEntry.desc.lSizeCompressed == fileEntry.desc.lSizeUncompressed, "Uncompressed file does not have the same commpressed %u and uncompressed file sizes %u",
-                fileEntry.desc.lSizeCompressed, fileEntry.desc.lSizeUncompressed);
-            memcpy(pUncompressed, pCompressed, fileEntry.desc.lSizeUncompressed);
-        }
-        switch (nError)
-        {
-        case Z_OK:
-            break;
-        case Z_MEM_ERROR:
-            AZ_Warning("Archive", false, "ZD_ERROR_ZLIB_NO_MEMORY: ZLib reported out-of-memory error");
-            return;
-        case Z_BUF_ERROR:
-            AZ_Warning("Archive", false, "ZD_ERROR_ZLIB_CORRUPTED_DATA: ZLib reported compressed stream buffer error");
-            return;
-        case Z_DATA_ERROR:
-            AZ_Warning("Archive", false, "ZD_ERROR_ZLIB_CORRUPTED_DATA: ZLib reported compressed stream data error");
-            return;
-        default:
-            AZ_Warning("Archive", false, "ZD_ERROR_ZLIB_FAILED: ZLib reported an unexpected unknown error");
-            return;
-        }
+                // Compare local file name with the CDR file name, they should match
+                AZStd::string_view zipFileName{ buffer.data() + sizeof(ZipFile::LocalFileHeader), localFileHeader->nFileNameLength };
+                AZStd::string_view cdrFileName{ reinterpret_cast<const char*>(pFileHeader + 1), pFileHeader->nFileNameLength };
+                if (zipFileName != cdrFileName)
+                {
+                    AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED: (%s)\n"
+                        " The file name in the local file header doesn't match the name in the global file header."
+                        " The archive content is inconsisten with the directory. Please check the archive.", m_szFilename.c_str());
+                }
 
-        if (nDestSize != fileEntry.desc.lSizeUncompressed)
-        {
-            AZ_Warning("Archive", false, "ZD_ERROR_CORRUPTED_DATA: Uncompressed stream doesn't match the size of uncompressed file stored in the archive file headers");
-            return;
-        }
+                // CDR and local "extra field" lengths may be different, should we compare them if they are equal?
 
-        uLong uCRC32 = AZ::Crc32((Bytef*)pUncompressed, nDestSize);
-        if (uCRC32 != fileEntry.desc.lCRC32)
-        {
-            AZ_Warning("Archive", false, "ZD_ERROR_CRC32_CHECK: Uncompressed stream CRC32 check failed");
-            return;
-        }
-    }
+                // make sure it's the same file and the fileEntry structure is properly initialized
+                AZ_Assert(fileEntry.nFileHeaderOffset == pFileHeader->lLocalHeaderOffset,
+                    "The file entry header offset doesn't match the file header local offst (%s)", m_szFilename.c_str());
 
+                if (fileEntry.nFileDataOffset >= m_nCDREndPos)
+                {
+                    AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED: (%s)\n"
+                        " The global file header declares the file which crosses the boundaries of the archive."
+                        " The archive is either corrupted or truncated, please try to repair it", m_szFilename.c_str());
+                }
 
-    //////////////////////////////////////////////////////////////////////////
-    // extracts the file path from the file header with subsequent information
-    // may, or may not, put all letters to lower-case (depending on whether the system is to be case-sensitive or not)
-    // it's the responsibility of the caller to ensure that the file name is in readable valid memory
-    char* CacheFactory::GetFilePath(const char* pFileName, uint16_t nFileNameLength)
-    {
-        static char strResult[AZ_MAX_PATH_LEN];
-        AZ_Assert(nFileNameLength < AZ_MAX_PATH_LEN, "Only filenames shorter than %zu can be copied from filename parameter", AZ_MAX_PATH_LEN);
-        memcpy(strResult, pFileName, nFileNameLength);
-        strResult[nFileNameLength] = 0;
-        for (int i = 0; i < nFileNameLength; i++)
-        {
-            strResult[i] = std::tolower(strResult[i], std::locale{});
+                // End Validation
+            }
         }
-
-        return strResult;
     }
 
     // seeks in the file relative to the starting position

+ 3 - 25
Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.h

@@ -39,7 +39,7 @@ namespace AZ::IO::ZipDir
 
         // initializes the internal structures
         // nFlags can have FLAGS_READ_ONLY flag, in this case the object will be opened only for reading
-        CacheFactory(InitMethodEnum nInitMethod, uint32_t nFlags = 0);
+        CacheFactory(InitMethod nInitMethod, uint32_t nFlags = 0);
         ~CacheFactory();
 
         // the new function creates a new cache
@@ -66,28 +66,6 @@ namespace AZ::IO::ZipDir
         // This function can actually modify strFilePath variable, make sure you use a copy of the real path.
         void AddFileEntry(char* strFilePath, const ZipFile::CDRFileHeader* pFileHeader, const SExtraZipFileData& extra);// throw (ErrorEnum);
 
-        // extracts the file path from the file header with subsequent information
-        // may, or may not, put all letters to lower-case (depending on whether the system is to be case-sensitive or not)
-        // it's the responsibility of the caller to ensure that the file name is in readable valid memory
-        char* GetFilePath(const ZipFile::CDRFileHeader* pFileHeader)
-        {
-            return GetFilePath((const char*)(pFileHeader + 1), pFileHeader->nFileNameLength);
-        }
-        // extracts the file path from the file header with subsequent information
-        // may, or may not, put all letters to lower-case (depending on whether the system is to be case-sensitive or not)
-        // it's the responsibility of the caller to ensure that the file name is in readable valid memory
-        char* GetFilePath(const ZipFile::LocalFileHeader* pFileHeader)
-        {
-            return GetFilePath((const char*)(pFileHeader + 1), pFileHeader->nFileNameLength);
-        }
-        // extracts the file path from the file header with subsequent information
-        // may, or may not, put all letters to lower-case (depending on whether the system is to be case-sensitive or not)
-        // it's the responsibility of the caller to ensure that the file name is in readable valid memory
-        char* GetFilePath(const char* pFileName, uint16_t nFileNameLength);
-
-        // validates (if the init method has the corresponding value) the given file/header
-        void Validate(const FileEntryBase& fileEntry);
-
         // initializes the actual data offset in the file in the fileEntry structure
         // searches to the local file header, reads it and calculates the actual offset in the file
         void InitDataOffset(FileEntryBase& fileEntry, const ZipFile::CDRFileHeader* pFileHeader);
@@ -104,7 +82,7 @@ namespace AZ::IO::ZipDir
         AZStd::string m_szFilename;
         CZipFile m_fileExt;
 
-        InitMethodEnum m_nInitMethod;
+        InitMethod m_nInitMethod;
         uint32_t m_nFlags;
         ZipFile::CDREnd m_CDREnd;
 
@@ -129,7 +107,7 @@ namespace AZ::IO::ZipDir
         ZipFile::CryCustomEncryptionHeader m_headerEncryption;
         ZipFile::CrySignedCDRHeader m_headerSignature;
         ZipFile::CryCustomExtendedHeader m_headerExtended;
-
     };
+
 }
 

+ 2 - 2
Code/Framework/AzFramework/AzFramework/Archive/ZipDirList.cpp

@@ -68,14 +68,14 @@ namespace AZ::IO::ZipDir
     {
         for (FileEntryTree::SubdirMap::iterator it = pTree->GetDirBegin(); it != pTree->GetDirEnd(); ++it)
         {
-            AddAllFiles(it->second.get(), (AZ::IO::Path(strRoot) / it->first).Native());
+            AddAllFiles(it->second.get(), (AZ::IO::Path(strRoot, AZ::IO::PosixPathSeparator) / it->first).Native());
         }
 
         for (FileEntryTree::FileMap::iterator it = pTree->GetFileBegin(); it != pTree->GetFileEnd(); ++it)
         {
             FileRecord rec;
             rec.pFileEntryBase = pTree->GetFileEntry(it);
-            rec.strPath = (AZ::IO::Path(strRoot) / it->first).Native();
+            rec.strPath = (AZ::IO::Path(strRoot, AZ::IO::PosixPathSeparator) / it->first).Native();
             push_back(rec);
         }
     }

+ 24 - 11
Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.h

@@ -119,19 +119,28 @@ namespace AZ::IO::ZipDir
         const char* m_szDescription;
     };
 
+#if defined(_RELEASE)
+    inline static constexpr bool IsReleaseConfig{ true };
+#else
+    inline static constexpr bool IsReleaseConfig{};
+#endif // _RELEASE
+
     // possible initialization methods
-    enum InitMethodEnum
+    enum class InitMethod
     {
-        // initialize as fast as possible, with minimal validation
-        ZD_INIT_FAST,
-        // after initialization, scan through all file headers, precache the actual file data offset values and validate the headers
-        ZD_INIT_FULL,
-        // scan all file headers and try to decompress the data, searching for corrupted files
-        ZD_INIT_VALIDATE_IN_MEMORY,
-        // store archive in memory
-        ZD_INIT_VALIDATE,
-        // maximum level of validation, checks for integrity of the archive
-        ZD_INIT_VALIDATE_MAX = ZD_INIT_VALIDATE
+        // initializes without any sort of extra validation steps
+        Default,
+
+        // initializes with extra validation steps
+        // not available in RELEASE
+        // will check CDR and local headers data match
+        ValidateHeaders,
+
+        // initializes with extra validation steps
+        // not available in RELEASE
+        // will check CDR and local headers data match
+        // will check file data CRC matches (when file is read)
+        FullValidation,
     };
 
     // Uncompresses raw (without wrapping) data that is compressed with method 8 (deflated) in the Zip file
@@ -184,7 +193,11 @@ namespace AZ::IO::ZipDir
         // the offset to the start of the next file's header - this
         // can be used to calculate the available space in zip file
         uint32_t nEOFOffset{};
+
+        // whether to check the CRC upon the next data read
+        bool bCheckCRCNextRead{};
     };
+
     // this is the record about the file in the Zip file.
     struct FileEntry
         : FileEntryBase

+ 1 - 1
Code/Framework/AzFramework/AzFramework/Network/AssetProcessorConnection.cpp

@@ -593,7 +593,7 @@ namespace AzFramework
             
             DebugMessage("StartThread: Starting %s", thread.m_desc.m_name);
             thread.m_join = false;
-            thread.m_thread = AZStd::thread(thread.m_main, &thread.m_desc);
+            thread.m_thread = AZStd::thread(thread.m_desc, thread.m_main);
         }
 
         void AssetProcessorConnection::JoinThread(ThreadState& thread, AZStd::condition_variable* wakeUpCondition /* = nullptr */)

+ 1 - 1
Code/Framework/AzFramework/AzFramework/TargetManagement/TargetManagementComponent.cpp

@@ -319,7 +319,7 @@ namespace AzFramework
         AZStd::thread_desc td;
         td.m_name = "TargetManager Thread";
         td.m_cpuId = AFFINITY_MASK_USERTHREADS;
-        m_threadHandle = AZStd::thread(AZStd::bind(&TargetManagementComponent::TickThread, this), &td);
+        m_threadHandle = AZStd::thread(td, AZStd::bind(&TargetManagementComponent::TickThread, this));
     }
 
     void TargetManagementComponent::Deactivate()

+ 20 - 18
Code/Framework/AzNetworking/AzNetworking/Utilities/TimedThread.cpp

@@ -26,27 +26,29 @@ namespace AzNetworking
     {
         m_running = true;
         m_joinable = true;
-        m_thread = AZStd::thread([this]()
-        {
-            OnStart();
-            while (m_running)
+        m_thread = AZStd::thread(
+            m_threadDesc,
+            [this]()
             {
-                const AZ::TimeMs startTimeMs = AZ::GetElapsedTimeMs();
-                OnUpdate(m_updateRate);
-                const AZ::TimeMs updateTimeMs = AZ::GetElapsedTimeMs() - startTimeMs;
-
-                if (m_updateRate > updateTimeMs)
+                OnStart();
+                while (m_running)
                 {
-                    AZStd::chrono::milliseconds sleepTimeMs(static_cast<int64_t>(m_updateRate - updateTimeMs));
-                    AZStd::this_thread::sleep_for(sleepTimeMs);
-                }
-                else if (m_updateRate < updateTimeMs)
-                {
-                    AZLOG(NET_TimedThread, "TimedThread bled %d ms", aznumeric_cast<int32_t>(updateTimeMs - m_updateRate));
+                    const AZ::TimeMs startTimeMs = AZ::GetElapsedTimeMs();
+                    OnUpdate(m_updateRate);
+                    const AZ::TimeMs updateTimeMs = AZ::GetElapsedTimeMs() - startTimeMs;
+
+                    if (m_updateRate > updateTimeMs)
+                    {
+                        AZStd::chrono::milliseconds sleepTimeMs(static_cast<int64_t>(m_updateRate - updateTimeMs));
+                        AZStd::this_thread::sleep_for(sleepTimeMs);
+                    }
+                    else if (m_updateRate < updateTimeMs)
+                    {
+                        AZLOG(NET_TimedThread, "TimedThread bled %d ms", aznumeric_cast<int32_t>(updateTimeMs - m_updateRate));
+                    }
                 }
-            }
-            OnStop();
-        }, &m_threadDesc);
+                OnStop();
+            });
     }
 
     void TimedThread::Stop()

+ 62 - 73
Code/Framework/AzToolsFramework/AzToolsFramework/Archive/ArchiveAPI.h

@@ -12,95 +12,84 @@
 #include <AzCore/EBus/EBus.h>
 #include <AzCore/std/string/string.h>
 #include <AzCore/Math/Uuid.h>
+#include <future>
 
 namespace AzToolsFramework
 {
-    // use bind if you need additional context.
-    // Parameters:
-    //  bool - If the archive command was successful or not.
-    typedef AZStd::function<void(bool)> ArchiveResponseCallback;
-    //  bool - If the archive command was successful or not.
-    //  AZStd::string - The console output from the command.
-    typedef AZStd::function<void(bool, AZStd::string)> ArchiveResponseOutputCallback;
-
-
     //! ArchiveCommands
     //! This bus handles messages relating to archive commands
     //! archive commands are ASYNCHRONOUS
     //! archive formats officially supported are .zip
-    //! do not block the main thread waiting for a response, it is not okay
-    //! you will not get a message delivered unless you tick the tickbus anyway!
     class ArchiveCommands
         : public AZ::EBusTraits
     {
     public:
-
-        using Bus = AZ::EBus<ArchiveCommands>;
-
+        // EBus Traits
         static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
         static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
         typedef AZStd::recursive_mutex MutexType;
         static const bool LocklessDispatch = true;
-        virtual ~ArchiveCommands() {}
-
-        //! Start an async task to extract an archive to the target directory
-        //! taskHandles are used to cancel a task at some point in the future and are provided by the caller per task.
-        //! Multiple tasks can be associated with the same handle
-        virtual void ExtractArchive(const AZStd::string& archivePath, const AZStd::string& destinationPath, AZ::Uuid taskHandle, const ArchiveResponseCallback& respCallback) = 0;
-        virtual void ExtractArchiveOutput(const AZStd::string& archivePath, const AZStd::string& destinationPath, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) = 0;
-        // Maintaining backwards API compatibility - ExtractArchiveBlocking below passes in extractWithRoot as an option
-        virtual void ExtractArchiveWithoutRoot(const AZStd::string& archivePath, const AZStd::string& destinationPath, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) = 0;
-
-        //! Start a sync task to extract an archive to the target directory
-        //! If you do not want to extract the root folder then set extractWithRootDirectory to false. 
-        virtual bool ExtractArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& destinationPath, bool extractWithRootDirectory) = 0;
-
-        //! Extract a single file asynchronously from the archive to the destination.  
-        //! Uses cwd if destinationPath empty.  overWrite = true for overwrite existing files, false for skipExisting
-        //! taskHandles are used to cancel a task at some point in the future and are provided by the caller per task.
-        //! Multiple tasks can be associated with the same handle
-        virtual void ExtractFile(const AZStd::string& archivePath, const AZStd::string& fileInArchive, const AZStd::string& destinationPath, bool overWrite, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) = 0;
-
-        //! Extract a single file from the archive to the destination and block until finished.  
-        //! Uses cwd if destinationPath empty.  overWrite = true for overwrite existing files, false for skipExisting
-        virtual bool ExtractFileBlocking(const AZStd::string& archivePath, const AZStd::string& fileInArchive, const AZStd::string& destinationPath, bool overWrite) = 0;
 
-        //! Start an async task to create an archive of the target directory (recursively)
-        //! taskHandles are used to cancel a task at some point in the future and are provided by the caller per task.
-        //! Multiple tasks can be associated with the same handle.
-        virtual void CreateArchive(const AZStd::string& archivePath, const AZStd::string& dirToArchive, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) = 0;
-
-        //! Start a sync task to create an archive of the target directory (recursively)
-        virtual bool CreateArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& dirToArchive) = 0;
-        
-        //! Start an async task to retrieve the list of files and their relative paths within an archive (recursively)
-        //! taskHandles are used to cancel a task at some point in the future and are provided by the caller per task.
-        //! Multiple tasks can be associated with the same handle.
-        virtual void ListFilesInArchive(const AZStd::string& archivePath, AZStd::vector<AZStd::string>& fileEntries, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) = 0;
-
-        //! Start a sync task to retrieve the list of files and their relative paths within an archive (recursively)
-        virtual bool ListFilesInArchiveBlocking(const AZStd::string& archivePath, AZStd::vector<AZStd::string>& fileEntries) = 0;
-
-        //! Start an async task to add a file to a preexisting archive. 
-        //! fileToAdd must be a relative path to the file from the working directory. The path to the file from the root of the archive will be the same as the relative path to the file on disk. 
-        //! taskHandles are used to cancel a task at some point in the future and are provided by the caller per task.
-        //! Multiple tasks can be associated with the same handle.
-        virtual void AddFileToArchive(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& fileToAdd, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) = 0;
-
-        //! Start a sync task to add a file to a preexisting archive. 
-        //! fileToAdd must be a relative path to the file from the working directory. The path to the file from the root of the archive will be the same as the relative path to the file on disk. 
-        virtual bool AddFileToArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& fileToAdd) = 0;
-
-        //! Start an async task to add files to a archive. 
-        //! File paths inside the list file must either be a relative path from the working directory or an absolute path. 
-        virtual void AddFilesToArchive(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& listFilePath, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) = 0;
-        
-        //! Start a sync task to add files to an archive. 
-        //! File paths inside the list file must either be a relative path from the working directory or an absolute path.
-        virtual bool AddFilesToArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& listFilePath) = 0;
-
-        //! Cancels tasks associtated with the given handle. Blocks until all tasks are cancelled.
-        virtual void CancelTasks(AZ::Uuid taskHandle) = 0;
+        virtual ~ArchiveCommands() = default;
+
+        //! Create an archive of the target directory (all files and subdirectories)
+        //! @param archivePath The path of the archive to create
+        //! @dirToArchive The directory to be added to the archive
+        //! @return Future (bool) which can obtain the success value of the operation
+        [[nodiscard]] virtual std::future<bool> CreateArchive(
+            const AZStd::string& archivePath,
+            const AZStd::string& dirToArchive) = 0;
+
+        //! Extract an archive to the target directory
+        //! @param archivePath The path of the archive to extract
+        //! @param destinationPath The directory where files will be extracted to
+        //! @return Future (bool) which can obtain the success value of the operation
+        [[nodiscard]] virtual std::future<bool> ExtractArchive(
+            const AZStd::string& archivePath,
+            const AZStd::string& destinationPath) = 0;
+
+        //! Extract a single file from the archive to the destination
+        //! Destination path should not be empty
+        //! @param archivePath The path of the archive to extract from
+        //! @param fileInArchive A path to a file, relative to root of archive
+        //! @param destinationPath The directory where file will be extracted to
+        //! @return Future (bool) which can obtain the success value of the operation
+        [[nodiscard]] virtual std::future<bool> ExtractFile(
+            const AZStd::string& archivePath,
+            const AZStd::string& fileInArchive,
+            const AZStd::string& destinationPath) = 0;
+
+        //! Retrieve the list of files contained in an archive (all files and subdirectories)
+        //! @param archivePath The path of the archive to list
+        //! @param outFileEntries An out parameter that will contain the file paths found
+        //! @return True if successful, false otherwise
+        virtual bool ListFilesInArchive(const AZStd::string& archivePath, AZStd::vector<AZStd::string>& outFileEntries) = 0;
+
+        //! Add a file to an archive
+        //! The archive might not exist yet
+        //! The file path relative to the working directory will be replicated in the archive
+        //! @param archivePath The path of the archive to add to
+        //! @param workingDirectory A directory that will be the starting path of the file to be added
+        //! @param fileToAdd A path to the file relative to the working directory
+        //! @return Future (bool) which can obtain the success value of the operation
+        [[nodiscard]] virtual std::future<bool> AddFileToArchive(
+            const AZStd::string& archivePath,
+            const AZStd::string& workingDirectory,
+            const AZStd::string& fileToAdd) = 0;
+
+        //! Add files to an archive provided from a file listing
+        //! The archive might not exist yet
+        //! File paths in the file list should be relative to root of the archive
+        //! @param archivePath The path of the archive to add to
+        //! @param workingDirectory A directory that will be the starting path of the list of files to add
+        //! @param listFilePath Full path to a text file that contains the list of files to add
+        //! @return Future (bool) which can obtain the success value of the operation
+        [[nodiscard]] virtual std::future<bool> AddFilesToArchive(
+            const AZStd::string& archivePath,
+            const AZStd::string& workingDirectory,
+            const AZStd::string& listFilePath) = 0;
     };
+
     using ArchiveCommandsBus = AZ::EBus<ArchiveCommands>;
+
 }; // namespace AzToolsFramework

+ 452 - 312
Code/Framework/AzToolsFramework/AzToolsFramework/Archive/ArchiveComponent.cpp

@@ -12,118 +12,98 @@
 #include <AzCore/Component/ComponentApplicationBus.h>
 #include <AzCore/Serialization/EditContext.h>
 
-#include <AzFramework/StringFunc/StringFunc.h>
-
+#include <AzFramework/Archive/INestedArchive.h>
+#include <AzFramework/Archive/ZipDirStructures.h>
 #include <AzFramework/Process/ProcessCommunicator.h>
 #include <AzFramework/Process/ProcessWatcher.h>
 #include <AzFramework/FileFunc/FileFunc.h>
 
+
 namespace AzToolsFramework
 {
-    // Forward declare platform specific functions
-    namespace Platform
-    {
-        AZStd::string GetZipExePath();
-        AZStd::string GetUnzipExePath();
-
-        AZStd::string GetCreateArchiveCommand(const AZStd::string& archivePath, const AZStd::string& dirToArchive);
-        AZStd::string GetExtractArchiveCommand(const AZStd::string& archivePath, const AZStd::string& destinationPath, bool includeRoot);
-        AZStd::string GetAddFileToArchiveCommand(const AZStd::string& archivePath, const AZStd::string& file);
-        AZStd::string GetAddFilesToArchiveCommand(const AZStd::string& archivePath, const AZStd::string& listFilePath);
-        AZStd::string GetExtractFileCommand(const AZStd::string& archivePath, const AZStd::string& fileInArchive, const AZStd::string& destinationPath, bool overWrite);
-        AZStd::string GetListFilesInArchiveCommand(const AZStd::string& archivePath);
-        void ParseConsoleOutputFromListFilesInArchive(const AZStd::string& consoleOutput, AZStd::vector<AZStd::string>& fileEntries);
-    }
+    constexpr const char s_traceName[] = "ArchiveComponent";
+    constexpr AZ::u32 s_compressionMethod = AZ::IO::INestedArchive::METHOD_DEFLATE;
+    constexpr AZ::s32 s_compressionLevel = AZ::IO::INestedArchive::LEVEL_NORMAL;
+    constexpr CompressionCodec::Codec s_compressionCodec = CompressionCodec::Codec::ZLIB;
 
-    const char s_traceName[] = "ArchiveComponent";
-    const unsigned int g_sleepDuration = 1;
-
-    // Echoes all results of stdout and stderr to console and never blocks
-    class ConsoleEchoCommunicator
+    namespace ArchiveUtils
     {
-    public:
-        ConsoleEchoCommunicator(AzFramework::ProcessCommunicator* communicator)
-            : m_communicator(communicator)
+        // Read a file's contents into a provided buffer.
+        // Does not add a zero byte at the end of the buffer.
+        // returns true if read was successful, false otherwise.
+        bool ReadFile(const AZ::IO::Path& filePath, AZ::IO::OpenMode openMode, AZStd::vector<char>& outBuffer)
         {
-        }
-
-        ~ConsoleEchoCommunicator()
-        {
-        }
+            auto fileIO = AZ::IO::FileIOBase::GetDirectInstance();
+            if (!fileIO)
+            {
+                return false;
+            }
 
-        // Call this periodically to drain the buffers
-        void Pump()
-        {
-            if (m_communicator->IsValid())
+            bool success = false;
+            AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
+            if (fileIO->Open(filePath.c_str(), openMode, fileHandle))
             {
-                AZ::u32 readBufferSize = 0;
-                AZStd::string readBuffer;
-                // Don't call readOutput unless there is output or else it will block...
-                readBufferSize = m_communicator->PeekOutput();
-                if (readBufferSize)
-                {
-                    readBuffer.resize_no_construct(readBufferSize + 1);
-                    readBuffer[readBufferSize] = '\0';
-                    m_communicator->ReadOutput(readBuffer.data(), readBufferSize);
-                    EchoBuffer(readBuffer);
-                }
-                readBufferSize = m_communicator->PeekError();
-                if (readBufferSize)
+                AZ::u64 fileSize = 0;
+                if (fileIO->Size(fileHandle, fileSize) && fileSize != 0)
                 {
-                    readBuffer.resize_no_construct(readBufferSize + 1);
-                    readBuffer[readBufferSize] = '\0';
-                    m_communicator->ReadError(readBuffer.data(), readBufferSize);
-                    EchoBuffer(readBuffer);
+                    outBuffer.resize_no_construct(fileSize);
+
+                    AZ::u64 bytesRead = 0;
+                    if (fileIO->Read(fileHandle, outBuffer.data(), fileSize, true, &bytesRead))
+                    {
+                        success = (fileSize == bytesRead);
+                    }
                 }
+
+                fileIO->Close(fileHandle);
             }
+
+            return success;
         }
 
-    private:
-        void EchoBuffer(const AZStd::string& buffer)
+        // Reads a text file that contains a list of file paths.
+        // Tokenize the file by lines.
+        // Calls the lineVisitor function for each line of the file.
+        void ProcessFileList(const AZ::IO::Path& filePath, AZStd::function<void(AZStd::string_view line)> lineVisitor)
         {
-            size_t startIndex = 0;
-            size_t endIndex = 0;
-            const size_t bufferSize = buffer.size();
-            for (size_t i = 0; i < bufferSize; ++i)
+            AZStd::vector<char> fileBuffer;
+            if (ReadFile(filePath, AZ::IO::OpenMode::ModeText | AZ::IO::OpenMode::ModeRead, fileBuffer))
             {
-                if (buffer[i] == '\n' || buffer[i] == '\0')
-                {
-                    endIndex = i;
-                    bool isEmptyMessage = (endIndex - startIndex == 1) && (buffer[startIndex] == '\r');
-                    if (!isEmptyMessage)
-                    {
-                        AZ_Printf(s_traceName, "%s", buffer.substr(startIndex, endIndex - startIndex).c_str());
-                    }
-                    startIndex = endIndex + 1;
-                }
+                AZ::StringFunc::TokenizeVisitor(AZStd::string_view{ fileBuffer.data(), fileBuffer.size() }, lineVisitor, "\n");
             }
         }
 
-        AzFramework::ProcessCommunicator* m_communicator = nullptr;
-    };
+    } // namespace ArchiveUtils
 
     void ArchiveComponent::Activate()
     {
-        m_zipExePath = Platform::GetZipExePath();
-        m_unzipExePath = Platform::GetUnzipExePath();
+        m_fileIO = AZ::IO::FileIOBase::GetDirectInstance();
+        if (m_fileIO == nullptr)
+        {
+            AZ_Error(s_traceName, false, "Failed to create a LocalFileIO instance!");
+        }
 
-        ArchiveCommands::Bus::Handler::BusConnect();
+        m_archive = AZ::Interface<AZ::IO::IArchive>::Get();
+        if (m_archive == nullptr)
+        {
+            AZ_Error(s_traceName, false, "Failed to get IArchive interface!");
+        }
+
+        ArchiveCommandsBus::Handler::BusConnect();
     }
 
     void ArchiveComponent::Deactivate()
     {
-        ArchiveCommands::Bus::Handler::BusDisconnect();
+        ArchiveCommandsBus::Handler::BusDisconnect();
 
-        AZStd::unique_lock<AZStd::mutex> lock(m_threadControlMutex);
-        for (auto pair : m_threadInfoMap)
+        m_fileIO = nullptr;
+        m_archive = nullptr;
+
+        for (AZStd::thread& t : m_threads)
         {
-            ThreadInfo& info = pair.second;
-            info.shouldStop = true;
-            m_cv.wait(lock, [&info]() {
-                return info.threads.size() == 0;
-            });
+            t.join();
         }
-        m_threadInfoMap.clear();
+        m_threads = {};
     }
 
     void ArchiveComponent::Reflect(AZ::ReflectContext * context)
@@ -132,7 +112,7 @@ namespace AzToolsFramework
         {
             serializeContext->Class<ArchiveComponent, AZ::Component>()
                 ->Version(2)
-                ->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector<AZ::Crc32>({ AZ_CRC("AssetBuilder", 0xc739c7d7) }))
+                ->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector<AZ::Crc32>({ AZ_CRC_CE("AssetBuilder") }))
                 ;
 
             if (AZ::EditContext* editContext = serializeContext->GetEditContext())
@@ -141,320 +121,480 @@ namespace AzToolsFramework
                     "Archive", "Handles creation and extraction of zip archives.")
                     ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
                     ->Attribute(AZ::Edit::Attributes::Category, "Editor")
-                    ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
+                    ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System"))
                     ;
             }
         }
     }
 
-    void ArchiveComponent::CreateArchive(const AZStd::string& archivePath, const AZStd::string& dirToArchive, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback)
+    std::future<bool> ArchiveComponent::CreateArchive(
+        const AZStd::string& archivePath,
+        const AZStd::string& dirToArchive)
     {
-        AZStd::string commandLineArgs = AZStd::string::format(R"(a -tzip -mx=1 "%s" -r "%s\*")", archivePath.c_str(), dirToArchive.c_str());
-        LaunchZipExe(m_zipExePath, commandLineArgs, respCallback, taskHandle);
-    }
-
-    bool ArchiveComponent::CreateArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& dirToArchive)
-    {
-        bool success = false;
-        auto createArchiveCallback = [&success](bool result, AZStd::string consoleOutput) {
-            success = result;
-        };
-
-        AZStd::string commandLineArgs = Platform::GetCreateArchiveCommand(archivePath, dirToArchive);
-
-        if (commandLineArgs.empty())
+        if (!CheckParamsForCreate(archivePath, dirToArchive))
         {
-            // The platform-specific implementation has already thrown its own error, no need to throw another one
-            return false;
+            std::promise<bool> p;
+            p.set_value(false);
+            return p.get_future();
         }
 
-        LaunchZipExe(m_zipExePath, commandLineArgs, createArchiveCallback, AZ::Uuid::CreateNull(), dirToArchive, false);
-        return success;
-    }
+        auto FnCreateArchive = [this, archivePath, dirToArchive](std::promise<bool>&& p) -> void
+        {
+            auto archive = m_archive->OpenArchive(archivePath, {}, AZ::IO::INestedArchive::FLAGS_CREATE_NEW);
+            if (!archive)
+            {
+                AZ_Error(s_traceName, false, "Failed to create archive file '%s'", archivePath.c_str());
+                p.set_value(false);
+                return;
+            }
 
-    void ArchiveComponent::ExtractArchive(const AZStd::string& archivePath, const AZStd::string& destinationPath, AZ::Uuid taskHandle, const ArchiveResponseCallback& respCallback)
-    {
-        ArchiveResponseOutputCallback responseHandler = [respCallback](bool result, AZStd::string /*outputStr*/) { respCallback(result); };
-        ExtractArchiveOutput(archivePath, destinationPath, taskHandle, responseHandler);
-    }
+            auto foundFiles = AzFramework::FileFunc::FindFilesInPath(dirToArchive, "*", true);
+            if (!foundFiles.IsSuccess())
+            {
+                AZ_Error(s_traceName, false, "Failed to find file listing under directory '%d'", dirToArchive.c_str());
+                p.set_value(false);
+                return;
+            }
 
-    void ArchiveComponent::ExtractArchiveOutput(const AZStd::string& archivePath, const AZStd::string& destinationPath, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback)
-    {
-        AZStd::string commandLineArgs = Platform::GetExtractArchiveCommand(archivePath, destinationPath, true);
+            bool success = true;
+            AZStd::vector<char> fileBuffer;
+            const AZ::IO::Path workingPath{ dirToArchive };
 
-        if (commandLineArgs.empty())
-        {
-            // The platform-specific implementation has already thrown its own error, no need to throw another one
-            return;
-        }
+            for (const auto& fileName : foundFiles.GetValue())
+            {
+                bool thisSuccess = false;
 
-        LaunchZipExe(m_unzipExePath, commandLineArgs, respCallback, taskHandle);
-    }
+                AZ::IO::PathView relativePath = AZ::IO::PathView{ fileName }.LexicallyRelative(workingPath);
 
-    void ArchiveComponent::ExtractArchiveWithoutRoot(const AZStd::string& archivePath, const AZStd::string& destinationPath, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback)
-    {
-        AZStd::string commandLineArgs = Platform::GetExtractArchiveCommand(archivePath, destinationPath, false);
+                AZ::IO::Path fullPath = (workingPath / relativePath);
+                if (ArchiveUtils::ReadFile(fullPath, AZ::IO::OpenMode::ModeRead, fileBuffer))
+                {
+                    int result = archive->UpdateFile(
+                        relativePath.Native(), fileBuffer.data(), fileBuffer.size(), s_compressionMethod,
+                        s_compressionLevel, s_compressionCodec);
+
+                    thisSuccess = (result == AZ::IO::ZipDir::ZD_ERROR_SUCCESS);
+                    AZ_Error(
+                        s_traceName, thisSuccess, "Error %d encountered while adding '%s' to archive '%.*s'", result, fileName.c_str(),
+                        AZ_STRING_ARG(archive->GetFullPath().Native()));
+                }
+                else
+                {
+                    AZ_Error(
+                        s_traceName, false, "Error encountered while reading '%s' to add to archive '%.*s'", fileName.c_str(),
+                        AZ_STRING_ARG(archive->GetFullPath().Native()));
+                }
 
-        if (commandLineArgs.empty())
-        {
-            // The platform-specific implementation has already thrown its own error, no need to throw another one
-            return;
-        }
+                success = (success && thisSuccess);
+            }
 
-        LaunchZipExe(m_unzipExePath, commandLineArgs, respCallback, taskHandle);
+            archive.reset();
+            p.set_value(success);
+        };
+
+        // Async task...
+        std::promise<bool> p;
+        std::future<bool> f = p.get_future();
+
+        AZStd::thread_desc threadDesc;
+        threadDesc.m_name = "Archive Task (Create)";
+        m_threads.emplace_back(threadDesc, FnCreateArchive, AZStd::move(p));
+        return f;
     }
 
-    void ArchiveComponent::ExtractFile(const AZStd::string& archivePath, const AZStd::string& fileInArchive, const AZStd::string& destinationPath, bool overWrite, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback)
+
+    std::future<bool> ArchiveComponent::ExtractArchive(
+        const AZStd::string& archivePath,
+        const AZStd::string& destinationPath)
     {
-        AZStd::string commandLineArgs = AzToolsFramework::Platform::GetExtractFileCommand(archivePath, fileInArchive, destinationPath, overWrite);
-        if (commandLineArgs.empty())
+        if (!CheckParamsForExtract(archivePath, destinationPath))
         {
-            // The platform-specific implementation has already thrown its own error, no need to throw another one
-            return;
+            std::promise<bool> p;
+            p.set_value(false);
+            return p.get_future();
         }
-        LaunchZipExe(m_unzipExePath, commandLineArgs, respCallback, taskHandle);
-    }
 
-    bool ArchiveComponent::ExtractFileBlocking(const AZStd::string& archivePath, const AZStd::string& fileInArchive, const AZStd::string& destinationPath, bool overWrite)
-    {
-        AZStd::string commandLineArgs = AzToolsFramework::Platform::GetExtractFileCommand(archivePath, fileInArchive, destinationPath, overWrite);
-        if (commandLineArgs.empty())
+        auto FnExtractArchive = [this, archivePath, destinationPath](std::promise<bool>&& p) -> void
         {
-            // The platform-specific implementation has already thrown its own error, no need to throw another one
-            return false;
-        }
+            auto archive = m_archive->OpenArchive(archivePath, {}, AZ::IO::INestedArchive::FLAGS_READ_ONLY);
+            if (!archive)
+            {
+                AZ_Error(s_traceName, false, "Failed to open archive file '%s'", archivePath.c_str());
+                p.set_value(false);
+                return;
+            }
 
-        bool success = false;
-        auto createArchiveCallback = [&success](bool result, AZStd::string consoleOutput) {
-            success = result;
-        };
-        LaunchZipExe(m_unzipExePath, commandLineArgs, createArchiveCallback);
-        return success;
-    }
+            AZStd::vector<AZ::IO::Path> filesInArchive;
+            if (int result = archive->ListAllFiles(filesInArchive); result != AZ::IO::ZipDir::ZD_ERROR_SUCCESS)
+            {
+                AZ_Error(s_traceName, false, "Failed to get list of files in archive '%s'", archivePath.c_str());
+                p.set_value(false);
+                return;
+            }
 
-    void ArchiveComponent::ListFilesInArchive(const AZStd::string& archivePath, AZStd::vector<AZStd::string>& fileEntries, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback)
-    {
-        AZStd::string commandLineArgs = Platform::GetListFilesInArchiveCommand(archivePath);
-        
-        auto parseOutput = [respCallback, &fileEntries](bool exitCode, AZStd::string consoleOutput)
-        {
-            Platform::ParseConsoleOutputFromListFilesInArchive(consoleOutput, fileEntries);
-            AZ::TickBus::QueueFunction(respCallback, exitCode, AZStd::move(consoleOutput));
-        };
-        LaunchZipExe(m_unzipExePath, commandLineArgs, parseOutput, taskHandle, "", true);
-    }
+            AZStd::vector<AZ::u8> fileBuffer;
+            AZ::IO::Path destination{ destinationPath };
+            AZ::u64 fileSize = 0;
+            AZ::u64 numFilesWritten = 0;
+            AZ::u64 bytesWritten = 0;
+            AZ::IO::INestedArchive::Handle srcHandle{};
+            AZ::IO::HandleType dstHandle = AZ::IO::InvalidHandle;
+            constexpr AZ::IO::OpenMode openMode =
+                (AZ::IO::OpenMode::ModeCreatePath | AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeUpdate);
+
+            for (const auto& filePath : filesInArchive)
+            {
+                srcHandle = archive->FindFile(filePath.Native());
+                AZ_Assert(srcHandle != nullptr, "File '%s' does not exist inside archive '%s'", filePath.c_str(), archivePath.c_str());
 
-    bool ArchiveComponent::ListFilesInArchiveBlocking(const AZStd::string& archivePath, AZStd::vector<AZStd::string>& fileEntries)
-    {
-        AZStd::string listOutput;
-        AZStd::string commandLineArgs = Platform::GetListFilesInArchiveCommand(archivePath.c_str());
-        bool success = false;
+                fileSize = (srcHandle != nullptr) ? archive->GetFileSize(srcHandle) : 0;
+                fileBuffer.resize_no_construct(fileSize);
+                if (auto result = archive->ReadFile(srcHandle, fileBuffer.data()); result != AZ::IO::ZipDir::ZD_ERROR_SUCCESS)
+                {
+                    AZ_Error(
+                        s_traceName, false, "Failed to read file '%s' in archive '%s' with error %d", filePath.c_str(), archivePath.c_str(),
+                        result);
+                    continue;
+                }
 
-        auto parseOutput = [&success, &fileEntries](bool result, AZStd::string consoleOutput)
-        {
-            Platform::ParseConsoleOutputFromListFilesInArchive(consoleOutput, fileEntries);
-            success = result;
+                AZ::IO::Path destinationFile = destination / filePath;
+                if (!m_fileIO->Open(destinationFile.c_str(), openMode, dstHandle))
+                {
+                    AZ_Error(s_traceName, false, "Failed to open '%s' for writing", destinationFile.c_str());
+                    continue;
+                }
+
+                if (!m_fileIO->Write(dstHandle, fileBuffer.data(), fileSize, &bytesWritten))
+                {
+                    AZ_Error(s_traceName, false, "Failed to write destination file '%s'", destinationFile.c_str());
+                }
+                else if (bytesWritten == fileSize)
+                {
+                    ++numFilesWritten;
+                }
+
+                m_fileIO->Close(dstHandle);
+            }
+
+            p.set_value(numFilesWritten == filesInArchive.size());
         };
-        LaunchZipExe(m_unzipExePath, commandLineArgs, parseOutput, AZ::Uuid::CreateNull(), "", true);
-        return success;
-    }
 
-    void ArchiveComponent::AddFileToArchive(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& fileToAdd, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback)
-    {
-        AZStd::string commandLineArgs = Platform::GetAddFileToArchiveCommand(archivePath, fileToAdd);
-        if (commandLineArgs.empty())
-        {
-            // The platform-specific implementation has already thrown its own error, no need to throw another one
-            return;
-        }
+        // Async task...
+        std::promise<bool> p;
+        std::future<bool> f = p.get_future();
 
-        LaunchZipExe(m_zipExePath, commandLineArgs, respCallback, taskHandle, workingDirectory);
+        AZStd::thread_desc threadDesc;
+        threadDesc.m_name = "Archive Task (Extract)";
+        m_threads.emplace_back(threadDesc, FnExtractArchive, AZStd::move(p));
+        return f;
     }
 
-    bool ArchiveComponent::AddFileToArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& fileToAdd)
+
+    std::future<bool> ArchiveComponent::ExtractFile(
+        const AZStd::string& archivePath,
+        const AZStd::string& fileInArchive,
+        const AZStd::string& destinationPath)
     {
-        AZStd::string commandLineArgs = Platform::GetAddFileToArchiveCommand(archivePath, fileToAdd);
-        if (commandLineArgs.empty())
+        if (!CheckParamsForExtract(archivePath, destinationPath))
         {
-            // The platform-specific implementation has already thrown its own error, no need to throw another one
-            return false;
+            std::promise<bool> p;
+            p.set_value(false);
+            return p.get_future();
         }
-        bool success = false;
-        auto addFileToArchiveCallback = [&success](bool result, AZStd::string consoleOutput) {
-            success = result;
-        };
 
-        LaunchZipExe(m_zipExePath, commandLineArgs, addFileToArchiveCallback, AZ::Uuid::CreateNull(), workingDirectory);
-        return success;
-    }
+        auto FnExtractFile = [this, archivePath, fileInArchive, destinationPath](std::promise<bool>&& p) -> void
+        {
+            auto archive = m_archive->OpenArchive(archivePath, {}, AZ::IO::INestedArchive::FLAGS_READ_ONLY);
+            if (!archive)
+            {
+                AZ_Error(s_traceName, false, "Failed to open archive file '%s'", archivePath.c_str());
+                p.set_value(false);
+                return;
+            }
 
-    bool ArchiveComponent::AddFilesToArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& listFilePath)
-    {
-        bool success = false;
+            AZ::IO::INestedArchive::Handle fileHandle = archive->FindFile(fileInArchive);
+            if (!fileHandle)
+            {
+                AZ_Error(s_traceName, false, "File '%s' does not exist inside archive '%s'", fileInArchive.c_str(), archivePath.c_str());
+                p.set_value(false);
+                return;
+            }
 
-        auto addFileToArchiveCallback = [&success](bool result, AZStd::string consoleOutput) {
-            success = result;
+            AZ::u64 fileSize = archive->GetFileSize(fileHandle);
+            AZStd::vector<AZ::u8> fileBuffer;
+            fileBuffer.resize_no_construct(fileSize);
+
+            if (auto result = archive->ReadFile(fileHandle, fileBuffer.data()); result != AZ::IO::ZipDir::ZD_ERROR_SUCCESS)
+            {
+                AZ_Error(
+                    s_traceName, false, "Failed to read file '%s' in archive '%s' with error %d", fileInArchive.c_str(),
+                    archivePath.c_str(), result);
+                p.set_value(false);
+                return;
+            }
+
+            AZ::IO::HandleType destFileHandle = AZ::IO::InvalidHandle;
+            AZ::IO::Path destinationFile{ destinationPath };
+            destinationFile /= fileInArchive;
+            AZ::IO::OpenMode openMode = (AZ::IO::OpenMode::ModeCreatePath | AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeUpdate);
+            if (!m_fileIO->Open(destinationFile.c_str(), openMode, destFileHandle))
+            {
+                AZ_Error(s_traceName, false, "Failed to open destination file '%s' for writing", destinationFile.c_str());
+                p.set_value(false);
+                return;
+            }
+
+            AZ::u64 bytesWritten = 0;
+            if (!m_fileIO->Write(destFileHandle, fileBuffer.data(), fileSize, &bytesWritten))
+            {
+                AZ_Error(s_traceName, false, "Failed to write destination file '%s'", destinationFile.c_str());
+            }
+
+            m_fileIO->Close(destFileHandle);
+            p.set_value(bytesWritten == fileSize);
         };
 
-        AZStd::string commandLineArgs = Platform::GetAddFilesToArchiveCommand(archivePath.c_str(), listFilePath.c_str());
+        // Async task...
+        std::promise<bool> p;
+        std::future<bool> f = p.get_future();
+
+        AZStd::thread_desc threadDesc;
+        threadDesc.m_name = "Archive Task (Extract Single)";
+        m_threads.emplace_back(threadDesc, FnExtractFile, AZStd::move(p));
+        return f;
+    }
+
 
-        if (commandLineArgs.empty())
+    bool ArchiveComponent::ListFilesInArchive(const AZStd::string& archivePath, AZStd::vector<AZStd::string>& outFileEntries)
+    {
+        if (!m_fileIO || !m_archive)
         {
-            // The platform-specific implementation has already thrown its own error, no need to throw another one
             return false;
         }
-        LaunchZipExe(m_zipExePath, commandLineArgs, addFileToArchiveCallback, AZ::Uuid::CreateNull(), workingDirectory);
-        return success;
-    }
 
-    void ArchiveComponent::AddFilesToArchive(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& listFilePath, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback)
-    {
-        AZStd::string commandLineArgs = Platform::GetAddFilesToArchiveCommand(archivePath, listFilePath);
-        if (commandLineArgs.empty())
+        if (!m_fileIO->Exists(archivePath.c_str()))
+        {
+            AZ_Error(s_traceName, false, "Archive '%s' does not exist!", archivePath.c_str());
+            return false;
+        }
+
+        auto archive = m_archive->OpenArchive(archivePath, {}, AZ::IO::INestedArchive::FLAGS_READ_ONLY);
+        if (!archive)
         {
-            // The platform-specific implementation has already thrown its own error, no need to throw another one
-            return;
+            AZ_Error(s_traceName, false, "Failed to open archive file '%s'", archivePath.c_str());
+            return false;
         }
 
-        LaunchZipExe(m_zipExePath, commandLineArgs, respCallback, taskHandle, workingDirectory);
+        AZStd::vector<AZ::IO::Path> fileEntries;
+        int result = archive->ListAllFiles(fileEntries);
+        outFileEntries.clear();
+        for (const auto& path : fileEntries)
+        {
+            outFileEntries.emplace_back(path.String());
+        }
+        return (result == AZ::IO::ZipDir::ZD_ERROR_SUCCESS);
     }
 
 
-    bool ArchiveComponent::ExtractArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& destinationPath, bool extractWithRootDirectory)
+    std::future<bool> ArchiveComponent::AddFileToArchive(
+        const AZStd::string& archivePath,
+        const AZStd::string& workingDirectory,
+        const AZStd::string& fileToAdd)
     {
-        AZStd::string commandLineArgs = Platform::GetExtractArchiveCommand(archivePath, destinationPath, extractWithRootDirectory);
-
-        if (commandLineArgs.empty())
+        if (!CheckParamsForAdd(workingDirectory, fileToAdd))
         {
-            // The platform-specific implementation has already thrown its own error, no need to throw another one
-            return false;
+            std::promise<bool> p;
+            p.set_value(false);
+            return p.get_future();
         }
 
-        bool success = false;
-        auto extractArchiveCallback = [&success](bool result, AZStd::string consoleOutput) {
-            success = result;
+        auto FnAddFileToArchive = [this, archivePath, workingDirectory, fileToAdd](std::promise<bool>&& p) -> void
+        {
+            auto archive = m_archive->OpenArchive(archivePath);
+            if (!archive)
+            {
+                AZ_Error(s_traceName, false, "Failed to open archive file '%s'", archivePath.c_str());
+                p.set_value(false);
+                return;
+            }
+
+            AZ::IO::Path workingPath{ workingDirectory };
+            AZ::IO::Path fullPath = workingPath / fileToAdd;
+            AZ::IO::PathView relativePath = AZ::IO::PathView{ fullPath }.LexicallyRelative(workingPath);
+
+            AZStd::vector<char> fileBuffer;
+            bool success = false;
+            if (ArchiveUtils::ReadFile(fullPath, AZ::IO::OpenMode::ModeRead, fileBuffer))
+            {
+                int result = archive->UpdateFile(
+                    relativePath.Native(), fileBuffer.data(), fileBuffer.size(), s_compressionMethod,
+                    s_compressionLevel, s_compressionCodec);
+
+                success = (result == AZ::IO::ZipDir::ZD_ERROR_SUCCESS);
+                AZ_Error(
+                    s_traceName, success, "Error %d encountered while adding '%s' to archive '%.*s'", result, fileToAdd.c_str(),
+                    AZ_STRING_ARG(archive->GetFullPath().Native()));
+            }
+            else
+            {
+                AZ_Error(
+                    s_traceName, false, "Error encountered while reading '%s' to add to archive '%.*s'", fileToAdd.c_str(),
+                    AZ_STRING_ARG(archive->GetFullPath().Native()));
+            }
+
+            archive.reset();
+            p.set_value(success);
         };
 
-        LaunchZipExe(m_unzipExePath, commandLineArgs, extractArchiveCallback);
-        return success;
+        // Async task...
+        std::promise<bool> p;
+        std::future<bool> f = p.get_future();
+
+        AZStd::thread_desc threadDesc;
+        threadDesc.m_name = "Archive Task (Add Single)";
+        m_threads.emplace_back(threadDesc, FnAddFileToArchive, AZStd::move(p));
+        return f;
     }
 
-    void ArchiveComponent::CancelTasks(AZ::Uuid taskHandle)
-    {
-        AZStd::unique_lock<AZStd::mutex> lock(m_threadControlMutex);
 
-        auto it = m_threadInfoMap.find(taskHandle);
-        if (it == m_threadInfoMap.end())
+    std::future<bool> ArchiveComponent::AddFilesToArchive(
+        const AZStd::string& archivePath,
+        const AZStd::string& workingDirectory,
+        const AZStd::string& listFilePath)
+    {
+        if (!CheckParamsForAdd(workingDirectory, listFilePath))
         {
-            return;
+            std::promise<bool> p;
+            p.set_value(false);
+            return p.get_future();
         }
 
-        ThreadInfo& info = it->second;
-        info.shouldStop = true;
-        m_cv.wait(lock, [&info]() {
-            return info.threads.size() == 0;
-        });
-        m_threadInfoMap.erase(it);
-    }
-    
-    void ArchiveComponent::LaunchZipExe(const AZStd::string& exePath, const AZStd::string& commandLineArgs, const ArchiveResponseOutputCallback& respCallback, AZ::Uuid taskHandle, const AZStd::string& workingDir, bool captureOutput)
-    {
-        auto sevenZJob = [=]()
+        auto FnAddFilesToArchive = [this, archivePath, workingDirectory, listFilePath](std::promise<bool>&& p) -> void
         {
-            if (!taskHandle.IsNull())
+            auto archive = m_archive->OpenArchive(archivePath);
+            if (!archive)
             {
-                AZStd::unique_lock<AZStd::mutex> lock(m_threadControlMutex);
-                m_threadInfoMap[taskHandle].threads.insert(AZStd::this_thread::get_id());
-                m_cv.notify_all();
+                AZ_Error(s_traceName, false, "Failed to open archive file '%s'", archivePath.c_str());
+                p.set_value(false);
+                return;
             }
 
-            AzFramework::ProcessLauncher::ProcessLaunchInfo info;
-            info.m_commandlineParameters = exePath + " " + commandLineArgs;
-            
-            info.m_showWindow = false;
-            if (!workingDir.empty())
-            {
-                info.m_workingDirectory = workingDir;
-            }
-            AZStd::unique_ptr<AzFramework::ProcessWatcher> watcher(AzFramework::ProcessWatcher::LaunchProcess(info, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_STDINOUT));
+            bool success = true; // starts true and turns false when any error is encountered.
+            AZ::IO::Path basePath{ workingDirectory };
 
-            AZStd::string consoleOutput;
-            AZ::u32 exitCode = static_cast<AZ::u32>(SevenZipExitCode::UserStoppedProcess);
-            if (watcher)
+            auto PerLineCallback = [&success, &basePath, &archive](AZStd::string_view filePathLine) -> void
             {
-                // callback requires output captured from 7z 
-                if (captureOutput)
+                AZStd::vector<char> fileBuffer;
+                AZ::IO::Path fullPath = (basePath / filePathLine);
+                if (ArchiveUtils::ReadFile(fullPath, AZ::IO::OpenMode::ModeRead, fileBuffer))
                 {
-                    AZStd::string consoleBuffer;
-                    while (watcher->IsProcessRunning(&exitCode))
-                    {
-                        if (!taskHandle.IsNull())
-                        {
-                            AZStd::unique_lock<AZStd::mutex> lock(m_threadControlMutex);
-                            if (m_threadInfoMap[taskHandle].shouldStop)
-                            {
-                                watcher->TerminateProcess(static_cast<AZ::u32>(SevenZipExitCode::UserStoppedProcess));
-                            }
-                        }
-                        watcher->WaitForProcessToExit(g_sleepDuration, &exitCode);
-                        AZ::u32 outputSize = watcher->GetCommunicator()->PeekOutput();
-                        if (outputSize)
-                        {
-                            consoleBuffer.resize(outputSize);
-                            watcher->GetCommunicator()->ReadOutput(consoleBuffer.data(), outputSize);
-                            consoleOutput += consoleBuffer;
-                        }
-                    }
+                    int result = archive->UpdateFile(
+                        filePathLine, fileBuffer.data(), fileBuffer.size(), s_compressionMethod,
+                        s_compressionLevel, s_compressionCodec);
+
+                    bool thisSuccess = (result == AZ::IO::ZipDir::ZD_ERROR_SUCCESS);
+                    success = (success && thisSuccess);
+                    AZ_Error(
+                        s_traceName, thisSuccess, "Error %d encountered while adding '%.*s' to archive '%.*s'", result,
+                        AZ_STRING_ARG(filePathLine), AZ_STRING_ARG(archive->GetFullPath().Native()));
                 }
                 else
                 {
-                    ConsoleEchoCommunicator echoCommunicator(watcher->GetCommunicator());
-                    while (watcher->IsProcessRunning(&exitCode))
-                    {
-                        if (!taskHandle.IsNull())
-                        {
-                            AZStd::unique_lock<AZStd::mutex> lock(m_threadControlMutex);
-                            if (m_threadInfoMap[taskHandle].shouldStop)
-                            {
-                                watcher->TerminateProcess(static_cast<AZ::u32>(SevenZipExitCode::UserStoppedProcess));
-                            }
-                        }
-                        watcher->WaitForProcessToExit(g_sleepDuration, &exitCode);
-                        echoCommunicator.Pump();
-                    }
+                    AZ_Error(
+                        s_traceName, false, "Error encountered while reading '%.*s' to add to archive '%.*s'", AZ_STRING_ARG(filePathLine),
+                        AZ_STRING_ARG(archive->GetFullPath().Native()));
                 }
-            }
+            };
 
-            if (taskHandle.IsNull())
-            {
-                respCallback(exitCode == static_cast<AZ::u32>(SevenZipExitCode::NoError), AZStd::move(consoleOutput));
-            }
-            else
+            ArchiveUtils::ProcessFileList(listFilePath, PerLineCallback);
+
+            archive.reset();
+            p.set_value(success);
+        };
+
+        // Async task...
+        std::promise<bool> p;
+        std::future<bool> f = p.get_future();
+
+        AZStd::thread_desc threadDesc;
+        threadDesc.m_name = "Archive Task (Add)";
+        m_threads.emplace_back(threadDesc, FnAddFilesToArchive, AZStd::move(p));
+        return f;
+    }
+
+
+    bool ArchiveComponent::CheckParamsForAdd(const AZStd::string& directory, const AZStd::string& file)
+    {
+        if (!m_fileIO || !m_archive)
+        {
+            return false;
+        }
+
+        if (!m_fileIO->IsDirectory(directory.c_str()))
+        {
+            AZ_Error(
+                s_traceName, false, "Working directory '%s' is not a directory or doesn't exist!", directory.c_str());
+            return false;
+        }
+
+        if (!file.empty())
+        {
+            auto filePath = AZ::IO::Path{ directory } / file;
+            if (!m_fileIO->Exists(filePath.c_str()) || m_fileIO->IsDirectory(filePath.c_str()))
             {
-                AZ::TickBus::QueueFunction(respCallback, (exitCode == static_cast<AZ::u32>(SevenZipExitCode::NoError)), AZStd::move(consoleOutput));
+                AZ_Error(s_traceName, false, "File list '%s' is a directory or doesn't exist!", filePath.c_str());
+                return false;
             }
+        }
+
+        return true;
+    }
 
-            if (!taskHandle.IsNull())
+    bool ArchiveComponent::CheckParamsForExtract(const AZStd::string& archive, const AZStd::string& directory)
+    {
+        if (!m_fileIO || !m_archive)
+        {
+            return false;
+        }
+
+        if (!m_fileIO->Exists(archive.c_str()))
+        {
+            AZ_Error(s_traceName, false, "Archive '%s' does not exist!", archive.c_str());
+            return false;
+        }
+
+        if (!m_fileIO->Exists(directory.c_str()))
+        {
+            if (!m_fileIO->CreatePath(directory.c_str()))
             {
-                AZStd::unique_lock<AZStd::mutex> lock(m_threadControlMutex);
-                ThreadInfo& tInfo = m_threadInfoMap[taskHandle];
-                tInfo.threads.erase(AZStd::this_thread::get_id());
-                m_cv.notify_all();
+                AZ_Error(s_traceName, false, "Failed to create destination directory '%s'", directory.c_str());
+                return false;
             }
-        };
-        if (!taskHandle.IsNull())
+        }
+
+        return true;
+    }
+
+    bool ArchiveComponent::CheckParamsForCreate(const AZStd::string& archive, const AZStd::string& directory)
+    {
+        if (!m_fileIO || !m_archive)
+        {
+            return false;
+        }
+
+        if (m_fileIO->Exists(archive.c_str()))
         {
-            AZStd::thread processThread(sevenZJob);
-            AZStd::unique_lock<AZStd::mutex> lock(m_threadControlMutex);
-            ThreadInfo& info = m_threadInfoMap[taskHandle];
-            m_cv.wait(lock, [&info, &processThread]() {
-                return info.threads.find(processThread.get_id()) != info.threads.end();
-            });
-            processThread.detach();
+            AZ_Error(s_traceName, false, "Archive file '%s' already exists, cannot create a new archive there!");
+            return false;
         }
-        else
+
+        if (!m_fileIO->IsDirectory(directory.c_str()))
         {
-            sevenZJob();
+            AZ_Error(s_traceName, false, "Directory '%s' is not a directory or doesn't exist!", directory.c_str());
+            return false;
         }
+
+        return true;
     }
+
 } // namespace AzToolsFramework

+ 45 - 49
Code/Framework/AzToolsFramework/AzToolsFramework/Archive/ArchiveComponent.h

@@ -10,80 +10,76 @@
 
 #include <AzCore/base.h>
 #include <AzCore/Component/Component.h>
+#include <AzCore/IO/FileIO.h>
 #include <AzCore/std/parallel/thread.h>
 #include <AzCore/std/parallel/conditional_variable.h>
 #include <AzCore/std/containers/set.h>
 #include <AzCore/std/containers/unordered_set.h>
 
+#include <AzFramework/Archive/IArchive.h>
 #include <AzToolsFramework/Archive/ArchiveAPI.h>
 
 namespace AzToolsFramework
 {
-    enum class SevenZipExitCode : AZ::u32
-    {
-        NoError = 0,
-        Warning = 1,
-        FatalError = 2,
-        CommandLineError = 7,
-        NotEnoughMemory = 8,
-        UserStoppedProcess = 255
-    };
-
-    // the ArchiveComponent's job is to execute zip commands.
-    // it parses the status of zip commands and returns results.
+    // the ArchiveComponent's job is to create and manipulate zip archives.
     class ArchiveComponent
         : public AZ::Component
-        , private ArchiveCommands::Bus::Handler
+        , private ArchiveCommandsBus::Handler
     {
     public:
-        AZ_COMPONENT(ArchiveComponent, "{A19EEA33-3736-447F-ACF7-DAA4B6A179AA}")
+        AZ_COMPONENT(ArchiveComponent, "{A19EEA33-3736-447F-ACF7-DAA4B6A179AA}");
 
         ArchiveComponent() = default;
         ~ArchiveComponent() override = default;
 
+        ArchiveComponent(const ArchiveComponent&) = delete;
+        ArchiveComponent& operator=(const ArchiveComponent&) = delete;
+
         //////////////////////////////////////////////////////////////////////////
         // AZ::Component overrides
         void Activate() override;
         void Deactivate() override;
         //////////////////////////////////////////////////////////////////////////
-    private:
+
+    protected:
         static void Reflect(AZ::ReflectContext* context);
 
         //////////////////////////////////////////////////////////////////////////
-        // ArchiveCommands::Bus::Handler overrides
-        void CreateArchive(const AZStd::string& archivePath, const AZStd::string& dirToArchive, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        bool CreateArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& dirToArchive) override;
-        bool ExtractArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& destinationPath, bool extractWithRootDirectory) override;
-        void ExtractArchive(const AZStd::string& archivePath, const AZStd::string& destinationPath, AZ::Uuid taskHandle, const ArchiveResponseCallback& respCallback) override;
-        void ExtractArchiveOutput(const AZStd::string& archivePath, const AZStd::string& destinationPath, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        void ExtractArchiveWithoutRoot(const AZStd::string& archivePath, const AZStd::string& destinationPath, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        void ExtractFile(const AZStd::string& archivePath, const AZStd::string& fileInArchive, const AZStd::string& destinationPath, bool overWrite, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        bool ExtractFileBlocking(const AZStd::string& archivePath, const AZStd::string& fileInArchive, const AZStd::string& destinationPath, bool overWrite) override;
-        void ListFilesInArchive(const AZStd::string& archivePath, AZStd::vector<AZStd::string>& fileEntries, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        bool ListFilesInArchiveBlocking(const AZStd::string& archivePath, AZStd::vector<AZStd::string>& fileEntries) override;
-        void AddFileToArchive(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& fileToAdd, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        bool AddFileToArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& fileToAdd) override;
-        bool AddFilesToArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& listFilePath) override;
-        void AddFilesToArchive(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& listFilePath, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        void CancelTasks(AZ::Uuid taskHandle) override;
+        // ArchiveCommandsBus::Handler overrides
+        [[nodiscard]] std::future<bool> CreateArchive(
+            const AZStd::string& archivePath,
+            const AZStd::string& dirToArchive) override;
+
+        [[nodiscard]] std::future<bool> ExtractArchive(
+            const AZStd::string& archivePath,
+            const AZStd::string& destinationPath) override;
+
+        [[nodiscard]] std::future<bool> ExtractFile(
+            const AZStd::string& archivePath,
+            const AZStd::string& fileInArchive,
+            const AZStd::string& destinationPath) override;
+
+        bool ListFilesInArchive(const AZStd::string& archivePath, AZStd::vector<AZStd::string>& outFileEntries) override;
+
+        [[nodiscard]] std::future<bool> AddFileToArchive(
+            const AZStd::string& archivePath,
+            const AZStd::string& workingDirectory,
+            const AZStd::string& fileToAdd) override;
+
+        [[nodiscard]] std::future<bool> AddFilesToArchive(
+            const AZStd::string& archivePath,
+            const AZStd::string& workingDirectory,
+            const AZStd::string& listFilePath) override;
         //////////////////////////////////////////////////////////////////////////
-        
-        // Launches the input zip exe as a background child process in a detached background thread, if the task handle is not null 
-        // otherwise launches input zip exe in the calling thread.
-        void LaunchZipExe(const AZStd::string& exePath, const AZStd::string& commandLineArgs, const ArchiveResponseOutputCallback& respCallback, AZ::Uuid taskHandle = AZ::Uuid::CreateNull(), const AZStd::string& workingDir = "", bool captureOutput = false);
-
-        AZStd::string m_zipExePath;
-        AZStd::string m_unzipExePath;
-
-        // Struct for tracking background threads/tasks
-        struct ThreadInfo
-        {
-            bool shouldStop = false;
-            AZStd::set<AZStd::thread::id> threads;
-        };
-
-        AZStd::mutex m_threadControlMutex; // Guards m_threadInfoMap
-        AZStd::condition_variable m_cv;
-        AZStd::unordered_map<AZ::Uuid, ThreadInfo> m_threadInfoMap;
+
+    private:
+        AZ::IO::FileIOBase* m_fileIO = nullptr;
+        AZ::IO::IArchive* m_archive = nullptr;
+        AZStd::vector<AZStd::thread> m_threads;
+
+        bool CheckParamsForAdd(const AZStd::string& directory, const AZStd::string& file);
+        bool CheckParamsForExtract(const AZStd::string& archive, const AZStd::string& directory);
+        bool CheckParamsForCreate(const AZStd::string& archive, const AZStd::string& directory);
     };
+
 } // namespace AzToolsFramework

+ 30 - 59
Code/Framework/AzToolsFramework/AzToolsFramework/Archive/NullArchiveComponent.cpp

@@ -16,91 +16,62 @@ namespace AzToolsFramework
 
     void NullArchiveComponent::Activate()
     {
-        ArchiveCommands::Bus::Handler::BusConnect();
+        ArchiveCommandsBus::Handler::BusConnect();
     }
 
     void NullArchiveComponent::Deactivate()
     {
-        ArchiveCommands::Bus::Handler::BusDisconnect();
+        ArchiveCommandsBus::Handler::BusDisconnect();
     }
 
-    bool NullArchiveComponent::ExtractArchiveBlocking(const AZStd::string& /*archivePath*/, const AZStd::string& /*destinationPath*/, bool /*extractWithRootDirectory*/)
+    std::future<bool> DefaultFuture()
     {
-        return false;
-    }
-
-    void NullArchiveComponent::ExtractArchive(const AZStd::string& /*archivePath*/, const AZStd::string& /*destinationPath*/, AZ::Uuid /*taskHandle*/, const ArchiveResponseCallback& respCallback)
-    {
-        AZ::TickBus::QueueFunction(respCallback, false);
+        std::promise<bool> p;
+        p.set_value(false);
+        return p.get_future();
     }
 
-    void NullArchiveComponent::ExtractArchiveOutput(const AZStd::string& /*archivePath*/, const AZStd::string& /*destinationPath*/, AZ::Uuid /*taskHandle*/, const ArchiveResponseOutputCallback& respCallback)
+    std::future<bool> NullArchiveComponent::CreateArchive(
+        const AZStd::string& /*archivePath*/,
+        const AZStd::string& /*dirToArchive*/)
     {
-        AZ::TickBus::QueueFunction(respCallback, false, AZStd::string());
+        return DefaultFuture();
     }
 
-    void NullArchiveComponent::ExtractArchiveWithoutRoot(const AZStd::string& /*archivePath*/, const AZStd::string& /*destinationPath*/, AZ::Uuid /*taskHandle*/, const ArchiveResponseOutputCallback& respCallback)
+    std::future<bool> NullArchiveComponent::ExtractArchive(
+        const AZStd::string& /*archivePath*/,
+        const AZStd::string& /*destinationPath*/)
     {
-        AZ::TickBus::QueueFunction(respCallback, false, AZStd::string());
+        return DefaultFuture();
     }
 
-    void NullArchiveComponent::ExtractFile(const AZStd::string& /*archivePath*/, const AZStd::string& /*fileInArchive*/, const AZStd::string& /*destinationPath*/, bool /*overWrite*/, AZ::Uuid /*taskHandle*/, const ArchiveResponseOutputCallback& respCallback)
+    std::future<bool> NullArchiveComponent::ExtractFile(
+        const AZStd::string& /*archivePath*/,
+        const AZStd::string& /*fileInArchive*/,
+        const AZStd::string& /*destinationPath*/)
     {
-        // Always report we failed to extract
-        AZ::TickBus::QueueFunction(respCallback, false, AZStd::string());
+        return DefaultFuture();
     }
 
-    bool NullArchiveComponent::ExtractFileBlocking(const AZStd::string& /*archivePath*/, const AZStd::string& /*fileInArchive*/, const AZStd::string& /*destinationPath*/, bool /*overWrite*/)
+    bool NullArchiveComponent::ListFilesInArchive(const AZStd::string& /*archivePath*/, AZStd::vector<AZStd::string>& /*outFileEntries*/)
     {
         return false;
     }
 
-    void NullArchiveComponent::ListFilesInArchive(const AZStd::string& /*archivePath*/, AZStd::vector<AZStd::string>& /*consoleOutput*/, AZ::Uuid /*taskHandle*/, const ArchiveResponseOutputCallback& respCallback)
+    std::future<bool> NullArchiveComponent::AddFileToArchive(
+        const AZStd::string& /*archivePath*/,
+        const AZStd::string& /*fileToAdd*/,
+        const AZStd::string& /*pathInArchive*/)
     {
-        // Always report we failed to extract
-        AZ::TickBus::QueueFunction(respCallback, false, AZStd::string());
-    }
-
-    bool NullArchiveComponent::ListFilesInArchiveBlocking(const AZStd::string& /*archivePath*/, AZStd::vector<AZStd::string>& /*consoleOutput*/)
-    {
-        return false;
-    }
-
-    void NullArchiveComponent::AddFileToArchive(const AZStd::string& /*archivePath*/, const AZStd::string& /*fileToAdd*/, const AZStd::string& /*pathInArchive*/, AZ::Uuid /*taskHandle*/, const ArchiveResponseOutputCallback& respCallback)
-    {
-        // Always report we failed to extract
-        AZ::TickBus::QueueFunction(respCallback, false, AZStd::string());
-    }
-
-    bool NullArchiveComponent::AddFileToArchiveBlocking(const AZStd::string& /*archivePath*/, const AZStd::string& /*fileToAdd*/, const AZStd::string& /*pathInArchive*/)
-    {
-        return false;
-    }
-
-    bool NullArchiveComponent::AddFilesToArchiveBlocking(const AZStd::string& /*archivePath*/, const AZStd::string& /*workingDirectory*/, const AZStd::string& /*listFilePath*/)
-    {
-        return false;
-    }
-
-    void NullArchiveComponent::AddFilesToArchive(const AZStd::string& /*archivePath*/, const AZStd::string& /*workingDirectory*/, const AZStd::string& /*listFilePath*/, AZ::Uuid /*taskHandle*/, const ArchiveResponseOutputCallback& respCallback)
-    {
-        // Always report we failed to extract
-        AZ::TickBus::QueueFunction(respCallback, false, AZStd::string());
-    }
-
-    void NullArchiveComponent::CreateArchive(const AZStd::string& /*archivePath*/, const AZStd::string& /*dirToArchive*/, AZ::Uuid /*taskHandle*/, const ArchiveResponseOutputCallback& respCallback)
-    {
-        // Always report we failed to extract
-        AZ::TickBus::QueueFunction(respCallback, false, AZStd::string());
-    }
-
-    bool NullArchiveComponent::CreateArchiveBlocking(const AZStd::string& /*archivePath*/, const AZStd::string& /*dirToArchive*/)
-    {
-        return false;
+        return DefaultFuture();
     }
 
-    void NullArchiveComponent::CancelTasks(AZ::Uuid /*taskHandle*/)
+    std::future<bool> NullArchiveComponent::AddFilesToArchive(
+        const AZStd::string& /*archivePath*/,
+        const AZStd::string& /*workingDirectory*/,
+        const AZStd::string& /*listFilePath*/)
     {
+        return DefaultFuture();
     }
 
     void NullArchiveComponent::Reflect(AZ::ReflectContext* context)

+ 26 - 18
Code/Framework/AzToolsFramework/AzToolsFramework/Archive/NullArchiveComponent.h

@@ -15,7 +15,7 @@ namespace AzToolsFramework
 {
     class NullArchiveComponent
         : public AZ::Component
-        , private ArchiveCommands::Bus::Handler
+        , private ArchiveCommandsBus::Handler
     {
     public:
         AZ_COMPONENT(NullArchiveComponent, "{D665B6B1-5FF4-4203-B19F-BBDB82587129}")
@@ -32,23 +32,31 @@ namespace AzToolsFramework
         static void Reflect(AZ::ReflectContext* context);
 
         //////////////////////////////////////////////////////////////////////////
-        // ArchiveCommands::Bus::Handler overrides
-         // ArchiveCommands::Bus::Handler overrides
-        void CreateArchive(const AZStd::string& archivePath, const AZStd::string& dirToArchive, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        bool CreateArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& dirToArchive) override;
-        bool ExtractArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& destinationPath, bool extractWithRootDirectory) override;
-        void ExtractArchive(const AZStd::string& archivePath, const AZStd::string& destinationPath, AZ::Uuid taskHandle, const ArchiveResponseCallback& respCallback) override;
-        void ExtractArchiveOutput(const AZStd::string& archivePath, const AZStd::string& destinationPath, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        void ExtractArchiveWithoutRoot(const AZStd::string& archivePath, const AZStd::string& destinationPath, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        void ExtractFile(const AZStd::string& archivePath, const AZStd::string& fileInArchive, const AZStd::string& destinationPath, bool overWrite, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        bool ExtractFileBlocking(const AZStd::string& archivePath, const AZStd::string& fileInArchive, const AZStd::string& destinationPath, bool overWrite) override;
-        void ListFilesInArchive(const AZStd::string& archivePath, AZStd::vector<AZStd::string>& consoleOutput, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        bool ListFilesInArchiveBlocking(const AZStd::string& archivePath, AZStd::vector<AZStd::string>& consoleOutput) override;
-        void AddFileToArchive(const AZStd::string& archivePath, const AZStd::string& fileToAdd, const AZStd::string& pathInArchive, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        bool AddFileToArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& fileToAdd, const AZStd::string& pathInArchive) override;
-        bool AddFilesToArchiveBlocking(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& listFilePath) override; 
-        void AddFilesToArchive(const AZStd::string& archivePath, const AZStd::string& workingDirectory, const AZStd::string& listFilePath, AZ::Uuid taskHandle, const ArchiveResponseOutputCallback& respCallback) override;
-        void CancelTasks(AZ::Uuid taskHandle) override;
+        // ArchiveCommandsBus::Handler overrides
+        [[nodiscard]] std::future<bool> CreateArchive(
+            const AZStd::string& archivePath,
+            const AZStd::string& dirToArchive) override;
+
+        [[nodiscard]] std::future<bool> ExtractArchive(
+            const AZStd::string& archivePath,
+            const AZStd::string& destinationPath) override;
+
+        [[nodiscard]] std::future<bool> ExtractFile(
+            const AZStd::string& archivePath,
+            const AZStd::string& fileInArchive,
+            const AZStd::string& destinationPath) override;
+
+        bool ListFilesInArchive(const AZStd::string& archivePath, AZStd::vector<AZStd::string>& outFileEntries) override;
+
+        [[nodiscard]] std::future<bool> AddFileToArchive(
+            const AZStd::string& archivePath,
+            const AZStd::string& workingDirectory,
+            const AZStd::string& fileToAdd) override;
+
+        [[nodiscard]] std::future<bool> AddFilesToArchive(
+            const AZStd::string& archivePath,
+            const AZStd::string& workingDirectory,
+            const AZStd::string& listFilePath) override;
         //////////////////////////////////////////////////////////////////////////
     };
 } // namespace AzToolsFramework

+ 17 - 10
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBundle/AssetBundleComponent.cpp

@@ -32,12 +32,10 @@ namespace AzToolsFramework
     const int NumOfBytesInMB = 1024 * 1024;
     const int ManifestFileSizeBufferInBytes = 10 * 1024; // 10 KB
     const float AssetCatalogFileSizeBufferPercentage = 1.0f;
-    using ArchiveCommandsBus = AzToolsFramework::ArchiveCommands::Bus;
     using AssetCatalogRequestBus = AZ::Data::AssetCatalogRequestBus;
 
     const char AssetBundleComponent::DeltaCatalogName[] = "DeltaCatalog.xml";
 
-    constexpr int SleepTimeMS = 250;
     constexpr int InjectFileRetryCount = 4;
 
 
@@ -136,7 +134,7 @@ namespace AzToolsFramework
         AZ_TracePrintf(logWindowName, "Gathering file entries in source pak file \"%s\".\n", sourcePak.c_str());
         bool result = false;
         AZStd::vector<AZStd::string> fileEntries;
-        ArchiveCommandsBus::BroadcastResult(result, &AzToolsFramework::ArchiveCommands::ListFilesInArchiveBlocking, normalizedSourcePakPath, fileEntries);
+        ArchiveCommandsBus::BroadcastResult(result, &AzToolsFramework::ArchiveCommandsBus::Events::ListFilesInArchive, normalizedSourcePakPath, fileEntries);
         // This ebus currently always returns false as the result, as it is believed that the 7z process is 
         //  being terminated by the user instead of ending gracefully. Check against an empty fileList instead
         //  as a result.
@@ -606,15 +604,17 @@ namespace AzToolsFramework
     {
         AZ_TracePrintf(logWindowName, "Injecting file (%s) into bundle (%s).\n", filePath.c_str(), archiveFilePath.c_str());
         bool fileAddedToArchive = false;
+        std::future<bool> fileAdded;
         int retryCount = InjectFileRetryCount;
+
         while (!fileAddedToArchive && retryCount)
         {
-            ArchiveCommandsBus::BroadcastResult(fileAddedToArchive, &AzToolsFramework::ArchiveCommands::AddFileToArchiveBlocking, archiveFilePath, workingDirectory, filePath);
+            ArchiveCommandsBus::BroadcastResult(fileAdded, &AzToolsFramework::ArchiveCommandsBus::Events::AddFileToArchive, archiveFilePath, workingDirectory, filePath);
             --retryCount;
+            fileAddedToArchive = fileAdded.get();
             if (!fileAddedToArchive && retryCount)
             {
                 AZ_Error(logWindowName, false, "Failed to insert file (%s) into bundle (%s). Retrying.", filePath.c_str(), archiveFilePath.c_str());
-                AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(SleepTimeMS));
             }
         }
 
@@ -627,7 +627,11 @@ namespace AzToolsFramework
     
     bool AssetBundleComponent::InjectFile(const AZStd::string& filePath, const AZStd::string& sourcePak)
     {
-        return InjectFile(filePath, sourcePak, "");
+        // When no working directory is specified, assume that the file being injected goes into the root of the archive.
+        // The filePath should be an absolute path, making the workingDirectory be the path leading up to the file.
+        AZ::IO::PathView fullFilePath{ filePath, AZ::IO::PosixPathSeparator };
+        AZ::IO::Path workingDir{ fullFilePath.ParentPath() };
+        return InjectFile(filePath, sourcePak, workingDir.c_str());
     }
 
     bool AssetBundleComponent::InjectFiles(const AZStd::vector<AZStd::string>& fileEntries, const AZStd::string& sourcePak, const char* workingDirectory)
@@ -668,8 +672,9 @@ namespace AzToolsFramework
             }
         }
 
-        bool filesAddedToArchive = false;
-        AzToolsFramework::ArchiveCommandsBus::BroadcastResult(filesAddedToArchive, &AzToolsFramework::ArchiveCommands::AddFilesToArchiveBlocking, sourcePak, workingDirectory, listFilePath);
+        std::future<bool> filesAdded;
+        AzToolsFramework::ArchiveCommandsBus::BroadcastResult(filesAdded, &AzToolsFramework::ArchiveCommands::AddFilesToArchive, sourcePak, workingDirectory, listFilePath);
+        bool filesAddedToArchive = filesAdded.get();
         if (!filesAddedToArchive)
         {
             AZ_Error(logWindowName, false, "Failed to insert files into bundle (%s).\n", sourcePak.c_str());
@@ -688,7 +693,6 @@ namespace AzToolsFramework
     {
         // open the manifest and deserialize it
         bool manifestExtracted = false;
-        const bool overwriteExisting = true;
 
         TemporaryDir tempDir(sourcePak);
         if (!tempDir.m_result)
@@ -698,7 +702,10 @@ namespace AzToolsFramework
 
         AZStd::string manifestFilePath;
         AzFramework::StringFunc::Path::ConstructFull(tempDir.m_tempFolderPath.c_str(), AzFramework::AssetBundleManifest::s_manifestFileName, manifestFilePath, true);
-        ArchiveCommandsBus::BroadcastResult(manifestExtracted, &ArchiveCommandsBus::Events::ExtractFileBlocking, sourcePak, AzFramework::AssetBundleManifest::s_manifestFileName, tempDir.m_tempFolderPath, overwriteExisting);
+
+        std::future<bool> extractResult;
+        ArchiveCommandsBus::BroadcastResult(extractResult, &ArchiveCommandsBus::Events::ExtractFile, sourcePak, AzFramework::AssetBundleManifest::s_manifestFileName, tempDir.m_tempFolderPath);
+        manifestExtracted = extractResult.get();
         if (!manifestExtracted)
         {
             AZ_Error(logWindowName, false, "Failed to extract existing manifest from archive \"%s\".", sourcePak.c_str());

+ 1 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/AssetBundle/AssetBundleComponent.h

@@ -57,7 +57,7 @@ namespace AzToolsFramework
         //! Returns true if the file at filePath was successfully injected into the bundle at sourcePak
         static bool InjectFile(const AZStd::string& filePath, const AZStd::string& sourcePak, const char* workingDirectory);
 
-        //! Inject the files with relative filePaths which espect to the working directory into the bundle at sourcePak
+        //! Inject the files with relative filePaths with respect to the working directory into the bundle at sourcePak
         //! Returns true if the file at filePath was successfully injected into the bundle at sourcePak
         static bool InjectFiles(const AZStd::vector<AZStd::string>& fileEntries, const AZStd::string& sourcePak, const char* workingDirectory);
 

+ 0 - 230
Code/Framework/AzToolsFramework/Platform/Linux/AzToolsFramework/Archive/ArchiveComponent_Linux.cpp

@@ -1,230 +0,0 @@
-/*
- * 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 <AzCore/std/string/string.h>
-#include <AzCore/Outcome/Outcome.h>
-#include <AzFramework/StringFunc/StringFunc.h>
-#include <AzFramework/IO/LocalFileIO.h>
-
-namespace AzToolsFramework
-{
-    namespace Platform
-    {
-        [[maybe_unused]] static const char ErrorChannel[] = "ArchiveComponent_Linux";
-
-        static const char ZipExePath[] = R"(/usr/bin/zip)";
-        static const char UnzipExePath[] = R"(/usr/bin/unzip)";
-
-        static const char CreateArchiveCmd[] = "-r \"%s\" . -i *";
-
-        static const char ExtractArchiveCmd[] = R"(-o "%s" -d "%s")";
-
-        static const char AddFileCmd[] = R"("%s" "%s")";
-
-        static const char ExtractFileCmd[] = R"(%s "%s" %s)";
-        static const char ExtractFileDestination[] = R"(%s "%s" "%s" -d "%s")";
-        static const char ExtractOverwrite[] = "-o";
-        static const char ExtractSkipExisting[] = "-n";
-        static const char ListFilesInArchiveCmd[] = "-l %s";
-
-        AZStd::string GetZipExePath()
-        {
-            return ZipExePath;
-        }
-
-        AZStd::string GetUnzipExePath()
-        {
-            return UnzipExePath;
-        }
-
-        AZ::Outcome<AZStd::string, AZStd::string> MakePath(const AZStd::string& path)
-        {
-            // Create the folder if it does not already exist
-            if (!AZ::IO::FileIOBase::GetInstance()->Exists(path.c_str()))
-            {
-                auto result = AZ::IO::FileIOBase::GetInstance()->CreatePath(path.c_str());
-                if (!result)
-                {
-                    return AZ::Failure(AZStd::string::format("Path creation failed. Input path: %s \n", path.c_str()));
-                }
-            }
-
-            return AZ::Success(path);
-        }
-
-        AZ::Outcome<AZStd::string, AZStd::string> MakeCreateArchivePath(const AZStd::string& archivePath)
-        {
-            // Remove the file name from the input path
-            // /some/folder/path/archive.zip -> /some/folder/path/
-            AZStd::string strippedArchivePath = archivePath;
-            AzFramework::StringFunc::Path::StripFullName(strippedArchivePath);
-
-            if (strippedArchivePath.empty())
-            {
-                return AZ::Failure(AZStd::string::format("Stripped path name is empty. Cancelling path creation. Input path: %s\n", archivePath.c_str()));
-            }
-
-            return MakePath(strippedArchivePath);
-        }
-
-        AZ::Outcome<AZStd::string, AZStd::string> MakeExtractArchivePath(const AZStd::string& archivePath, const AZStd::string& destinationPath, bool includeRoot)
-        {
-            if(!includeRoot)
-            {
-                // Create the folder for the input destination path with no modifications
-                // /path/to/destination/
-                return MakePath(destinationPath);
-            }
-
-            // Get the name of the input archive. This will be the name of the root folder for the archive extraction
-            // /some/folder/path/archive.zip -> archive
-            AZStd::string zipFileName;
-            bool result = AzFramework::StringFunc::Path::GetFileName(archivePath.c_str(), zipFileName);
-            if(!result)
-            {
-                return AZ::Failure(AZStd::string::format("Failed to get name of zip file from the archive path. Cancelling path creation. \n Input Archive Path: %s \n", archivePath.c_str()));
-            }
-
-            // Append the root folder name to the end of the destination path
-            // /path/to/destination/ + archive -> /path/to/destination/archive
-            AZStd::string destinationPathWithRoot;
-            result = AzFramework::StringFunc::Path::Join(destinationPath.c_str(), zipFileName.c_str(), destinationPathWithRoot);
-            if(!result)
-            {
-                return AZ::Failure(AZStd::string::format("Failed to append zip file name to the destination path. Cancelling path creation. \n Destination Path: %s \n Zip file name: %s \n", destinationPath.c_str(), zipFileName.c_str()));
-            }
-
-            // Append a separator so that it is formatted like a folder
-            // /path/to/destination/archive -> /path/to/destination/archive/
-            AzFramework::StringFunc::Path::AppendSeparator(destinationPathWithRoot);
-            return MakePath(destinationPathWithRoot);
-        }
-
-        AZStd::string GetCreateArchiveCommand(const AZStd::string& archivePath, const AZStd::string& dirToArchive)
-        {
-            auto pathCreationResult = MakeCreateArchivePath(archivePath);
-            if (!pathCreationResult)
-            {
-                AZ_Error(ErrorChannel, false, "%s", pathCreationResult.GetError().c_str());
-                return "";
-            }
-            AZ_UNUSED(dirToArchive);
-            return AZStd::string::format(CreateArchiveCmd, archivePath.c_str());
-        }
-
-        AZStd::string GetExtractArchiveCommand(const AZStd::string& archivePath, const AZStd::string& destinationPath, bool includeRoot)
-        {
-            auto pathCreationResult = MakeExtractArchivePath(archivePath, destinationPath, includeRoot);
-            if (!pathCreationResult)
-            {
-                AZ_Error(ErrorChannel, false, "%s", pathCreationResult.GetError().c_str());
-                return "";
-            }
-
-            return AZStd::string::format(ExtractArchiveCmd, archivePath.c_str(), pathCreationResult.GetValue().c_str());
-        }
-
-        AZStd::string GetAddFilesToArchiveCommand(const AZStd::string& /*archivePath*/, const AZStd::string& /*listFilePath*/)
-        {
-            // Adding files into a archive using a list file is not currently supported
-            return {};
-        }
-
-        bool IsAddFilesToArchiveCommandSupported()
-        {
-            // Adding files into a archive using a list file is not currently supported
-            return false;
-        }
-
-        AZStd::string GetAddFileToArchiveCommand(const AZStd::string& archivePath, const AZStd::string& file)
-        {
-            if (!MakeCreateArchivePath(archivePath).IsSuccess())
-            {
-                AZ_Error(ErrorChannel, false, "Unable to make path for ( %s ).\n", archivePath.c_str());
-                return {};
-            }
-            return AZStd::string::format(AddFileCmd, archivePath.c_str(), file.c_str());
-        }
-
-        AZStd::string GetExtractFileCommand(const AZStd::string& archivePath, const AZStd::string& fileInArchive, const AZStd::string& destinationPath, bool overWrite)
-        {
-            AZStd::string commandLineArgs;
-            if (destinationPath.empty())
-            {
-                // Extract file in archive from archive path to the current directory, overwriting a file of the same name that exists there.
-                commandLineArgs = AZStd::string::format(ExtractFileCmd, overWrite ? ExtractOverwrite : ExtractSkipExisting, archivePath.c_str(), fileInArchive.c_str());
-            }
-            else
-            {
-                if (!MakePath(destinationPath).IsSuccess())
-                {
-                    AZ_Error(ErrorChannel, false, "Unable to make path ( %s ).\n", destinationPath.c_str());
-                    return {};
-                }
-                // Extract file in archive from archive path to destinationPath, overwriting a file of the same name that exists there.
-                commandLineArgs = AZStd::string::format(ExtractFileDestination, overWrite ? ExtractOverwrite : ExtractSkipExisting, archivePath.c_str(), fileInArchive.c_str(), destinationPath.c_str());
-            }
-
-            return commandLineArgs;
-        }
-
-        AZStd::string GetListFilesInArchiveCommand(const AZStd::string& archivePath)
-        {
-            AZStd::string commandLineArgs = AZStd::string::format(ListFilesInArchiveCmd, archivePath.c_str());
-            return commandLineArgs;
-        }
-
-        /*
-        Sample Console Output of the unzip list command
-
-         Archive:  /var/folders/1q/12nyzqc913qgm532y2c98mnm6w4_qv/T/ArchiveTests-ra8oMy/TestArchive.pak
-         Length      Date    Time    Name
-         ---------  ---------- -----   ----
-                 0  10-14-2019 15:22   testfolder/
-                 1  10-14-2019 15:22   testfolder/folderfile.txt
-                 1  10-14-2019 15:22   basicfile.txt
-                 1  10-14-2019 15:22   basicfile2.txt
-                 0  10-14-2019 15:22   testfolder2/
-                 1  10-14-2019 15:22   testfolder2/sharedfolderfile2.txt
-                 1  10-14-2019 15:22   testfolder2/sharedfolderfile.txt
-                 0  10-14-2019 15:22   testfolder3/
-                 0  10-14-2019 15:22   testfolder3/testfolder4/
-                 1  10-14-2019 15:22   testfolder3/testfolder4/depthfile.bat
-         ---------                     -------
-                 6                     10 files
-         */
-
-        void ParseConsoleOutputFromListFilesInArchive(const AZStd::string& consoleOutput, AZStd::vector<AZStd::string>& fileEntries)
-        {
-            AZStd::vector<AZStd::string> fileEntryData;
-            AzFramework::StringFunc::Tokenize(consoleOutput.c_str(), fileEntryData, "\n");
-            int startingLineIdx = 3; // first line that might contain the file name
-            for (size_t lineIdx = startingLineIdx; lineIdx < fileEntryData.size(); ++lineIdx)
-            {
-                AZStd::string& line = fileEntryData[lineIdx];
-                AZStd::vector<AZStd::string> lineEntryData;
-                AzFramework::StringFunc::Tokenize(line.c_str(), lineEntryData, " ");
-                AZStd::string& fileName = lineEntryData.back();
-
-                if(fileName.back() == AZ_CORRECT_FILESYSTEM_SEPARATOR)
-                {
-                    // if the filename ends with a separator
-                    // than it indicates that this is a directory
-                    continue;
-                }
-
-                if(fileName.compare("-------") == 0)
-                {
-                    return;
-                }
-
-                fileEntries.emplace_back(fileName);
-            }
-        }
-    } // namespace Platform
-} // namespace AzToolsFramework

+ 0 - 1
Code/Framework/AzToolsFramework/Platform/Linux/platform_linux_files.cmake

@@ -7,5 +7,4 @@
 #
 
 set(FILES
-    AzToolsFramework/Archive/ArchiveComponent_Linux.cpp
 )

+ 0 - 263
Code/Framework/AzToolsFramework/Platform/Mac/AzToolsFramework/Archive/ArchiveComponent_Mac.cpp

@@ -1,263 +0,0 @@
-/*
- * 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 <AzCore/std/string/string.h>
-#include <AzCore/Outcome/Outcome.h>
-#include <AzFramework/StringFunc/StringFunc.h>
-#include <AzFramework/IO/LocalFileIO.h>
-
-namespace AzToolsFramework
-{
-    namespace Platform
-    {
-        const char ErrorChannel[] = "ArchiveComponent_OSX";
-
-        const char ZipExePath[] = R"(/usr/bin/zip)";
-        const char UnzipExePath[] = R"(/usr/bin/unzip)";
-
-        // v  Requires investigation, the correct cmd should be R"(-r "%s" "%s/")" but tests fail
-        const char CreateArchiveCmd[] = R"(-r "%s" .)";
-
-        const char ExtractArchiveCmd[] = R"(-o "%s" -d "%s")";
-        
-        const char AddFileCmd[] = R"("%s" "%s" -X)";
-        const char AddFilesCmd[] = R"("%s" -X %s)";
-
-        const char ExtractFileCmd[] = R"(%s "%s" %s)";
-        const char ExtractFileDestination[] = R"(%s "%s" "%s" -d "%s")";
-        const char ExtractOverwrite[] = "-o";
-        const char ExtractSkipExisting[] = "-n";
-        const char ListFilesInArchiveCmd[] = "-l %s";
-
-        AZStd::string GetZipExePath()
-        {
-            return ZipExePath;
-        }
-
-        AZStd::string GetUnzipExePath()
-        {
-            return UnzipExePath;
-        }
-        
-        AZ::Outcome<AZStd::string, AZStd::string> MakePath(const AZStd::string& path)
-        {
-            // Create the folder if it does not already exist
-            if (!AZ::IO::FileIOBase::GetInstance()->Exists(path.c_str()))
-            {
-                auto result = AZ::IO::FileIOBase::GetInstance()->CreatePath(path.c_str());
-                if (!result)
-                {
-                    return AZ::Failure(AZStd::string::format("Path creation failed. Input path: %s \n", path.c_str()));
-                }
-            }
-            
-            return AZ::Success(path);
-        }
-        
-        AZ::Outcome<AZStd::string, AZStd::string> MakeCreateArchivePath(const AZStd::string& archivePath)
-        {
-            // Remove the file name from the input path
-            // /some/folder/path/archive.zip -> /some/folder/path/
-            AZStd::string strippedArchivePath = archivePath;
-            AzFramework::StringFunc::Path::StripFullName(strippedArchivePath);
-            
-            if (strippedArchivePath.empty())
-            {
-                return AZ::Failure(AZStd::string::format("Stripped path name is empty. Cancelling path creation. Input path: %s\n", archivePath.c_str()));
-            }
-
-            return MakePath(strippedArchivePath);
-        }
-        
-        AZ::Outcome<AZStd::string, AZStd::string> MakeExtractArchivePath(const AZStd::string& archivePath, const AZStd::string& destinationPath, bool includeRoot)
-        {
-            if(!includeRoot)
-            {
-                // Create the folder for the input destination path with no modifications
-                // /path/to/destination/
-                return MakePath(destinationPath);
-            }
-            
-            // Get the name of the input archive. This will be the name of the root folder for the archive extraction
-            // /some/folder/path/archive.zip -> archive
-            AZStd::string zipFileName;
-            bool result = AzFramework::StringFunc::Path::GetFileName(archivePath.c_str(), zipFileName);
-            if(!result)
-            {
-                return AZ::Failure(AZStd::string::format("Failed to get name of zip file from the archive path. Cancelling path creation. \n Input Archive Path: %s \n", archivePath.c_str()));
-            }
-            
-            // Append the root folder name to the end of the destination path
-            // /path/to/destination/ + archive -> /path/to/destination/archive
-            AZStd::string destinationPathWithRoot;
-            result = AzFramework::StringFunc::Path::Join(destinationPath.c_str(), zipFileName.c_str(), destinationPathWithRoot);
-            if(!result)
-            {
-                return AZ::Failure(AZStd::string::format("Failed to append zip file name to the destination path. Cancelling path creation. \n Destination Path: %s \n Zip file name: %s \n", destinationPath.c_str(), zipFileName.c_str()));
-            }
-            
-            // Append a separator so that it is formatted like a folder
-            // /path/to/destination/archive -> /path/to/destination/archive/
-            AzFramework::StringFunc::Path::AppendSeparator(destinationPathWithRoot);
-            return MakePath(destinationPathWithRoot);
-        }
-        
-        AZStd::string GetCreateArchiveCommand(const AZStd::string& archivePath, const AZStd::string& dirToArchive)
-        {
-            auto pathCreationResult = MakeCreateArchivePath(archivePath);
-            if (!pathCreationResult.IsSuccess())
-            {
-                AZ_Error(ErrorChannel, false, pathCreationResult.GetError().c_str());
-                return "";
-            }
-
-            // LY-116692. Requires proper investigation, the correct format should be:
-            // AZStd::string::format(CreateArchiveCmd, archivePath.c_str(), dirToArchive.c_str());
-            // but unit test ArchiveTest.ListFilesInArchiveBlocking_FilesAtThreeDepths_FilesFound fails
-            AZ_UNUSED(dirToArchive);
-            return AZStd::string::format(CreateArchiveCmd, archivePath.c_str());
-        }
-
-        AZStd::string GetExtractArchiveCommand(const AZStd::string& archivePath, const AZStd::string& destinationPath, bool includeRoot)
-        {
-            auto pathCreationResult = MakeExtractArchivePath(archivePath, destinationPath, includeRoot);
-            if (!pathCreationResult)
-            {
-                AZ_Error(ErrorChannel, false, pathCreationResult.GetError().c_str());
-                return "";
-            }
-            
-            return AZStd::string::format(ExtractArchiveCmd, archivePath.c_str(), pathCreationResult.GetValue().c_str());
-        }
-
-        AZStd::string GetAddFilesToArchiveCommand(const AZStd::string& archivePath, const AZStd::string& listFilePath)
-        {
-            auto pathCreationResult = MakeCreateArchivePath(archivePath);
-            if (!pathCreationResult)
-            {
-                AZ_Error(ErrorChannel, false, pathCreationResult.GetError().c_str());
-                return "";
-            }
-            AZStd::string fileListStr;
-
-            {
-                AZ::IO::FileIOStream fileStream(listFilePath.c_str(), AZ::IO::OpenMode::ModeRead | AZ::IO::OpenMode::ModeText);
-                if (fileStream.IsOpen())
-                {
-                    AZ::IO::SizeType length = fileStream.GetLength();
-                    AZStd::vector<char> charBuffer;
-                    charBuffer.resize_no_construct(length + 1);
-
-                    fileStream.Read(length, charBuffer.data());
-                    charBuffer.back() = 0;
-
-                    fileListStr.append("\"");
-                    fileListStr.insert(1, charBuffer.data());
-                    AzFramework::StringFunc::Replace(fileListStr, "\n", "\" \"");
-                    fileListStr.append("\"");
-                }
-                else
-                {
-                    AZ_Error(ErrorChannel, false, "Unable to read list file ( %s ) \n", listFilePath.c_str());
-                    return "";
-                }
-            }
-
-            return AZStd::string::format(AddFilesCmd, archivePath.c_str(), fileListStr.c_str());
-        }
-
-        AZStd::string GetAddFileToArchiveCommand(const AZStd::string& archivePath, const AZStd::string& file)
-        {
-            auto pathCreationResult = MakeCreateArchivePath(archivePath);
-            if (!pathCreationResult)
-            {
-                AZ_Error(ErrorChannel, false, pathCreationResult.GetError().c_str());
-                return "";
-            }
-
-            return AZStd::string::format(AddFileCmd, archivePath.c_str(), file.c_str());
-        }
-
-        AZStd::string GetExtractFileCommand(const AZStd::string& archivePath, const AZStd::string& fileInArchive, const AZStd::string& destinationPath, bool overWrite)
-        {
-            AZStd::string commandLineArgs;
-            if (destinationPath.empty())
-            {
-                // Extract file in archive from archive path to the current directory, overwriting a file of the same name that exists there.
-                commandLineArgs = AZStd::string::format(ExtractFileCmd, overWrite ? ExtractOverwrite : ExtractSkipExisting, archivePath.c_str(), fileInArchive.c_str());
-            }
-            else
-            {
-                if (!MakePath(destinationPath).IsSuccess())
-                {
-                    AZ_Error(ErrorChannel, false, "Unable to make path ( %s ).\n", destinationPath.c_str());
-                    return "";
-                }
-                // Extract file in archive from archive path to destinationPath, overwriting a file of the same name that exists there.
-                commandLineArgs = AZStd::string::format(ExtractFileDestination, overWrite ? ExtractOverwrite : ExtractSkipExisting, archivePath.c_str(), fileInArchive.c_str(), destinationPath.c_str());
-            }
-
-            return commandLineArgs;
-        }
-        
-        AZStd::string GetListFilesInArchiveCommand(const AZStd::string& archivePath)
-        {
-            AZStd::string commandLineArgs = AZStd::string::format(ListFilesInArchiveCmd, archivePath.c_str());
-            return commandLineArgs;
-        }
-        
-        /*
-        Sample Console Output of the unzip list command
-        
-         Archive:  /var/folders/1q/12nyzqc913qgm532y2c98mnm6w4_qv/T/ArchiveTests-ra8oMy/TestArchive.pak
-         Length      Date    Time    Name
-         ---------  ---------- -----   ----
-                 0  10-14-2019 15:22   testfolder/
-                 1  10-14-2019 15:22   testfolder/folderfile.txt
-                 1  10-14-2019 15:22   basicfile.txt
-                 1  10-14-2019 15:22   basicfile2.txt
-                 0  10-14-2019 15:22   testfolder2/
-                 1  10-14-2019 15:22   testfolder2/sharedfolderfile2.txt
-                 1  10-14-2019 15:22   testfolder2/sharedfolderfile.txt
-                 0  10-14-2019 15:22   testfolder3/
-                 0  10-14-2019 15:22   testfolder3/testfolder4/
-                 1  10-14-2019 15:22   testfolder3/testfolder4/depthfile.bat
-         ---------                     -------
-                 6                     10 files
-         */
-
-        void ParseConsoleOutputFromListFilesInArchive(const AZStd::string& consoleOutput, AZStd::vector<AZStd::string>& fileEntries)
-        {
-            AZStd::vector<AZStd::string> fileEntryData;
-            AzFramework::StringFunc::Tokenize(consoleOutput.c_str(), fileEntryData, "\n");
-            int startingLineIdx = 3; // first line that might contain the file name
-            for (size_t lineIdx = startingLineIdx; lineIdx < fileEntryData.size(); ++lineIdx)
-            {
-                AZStd::string& line = fileEntryData[lineIdx];
-                AZStd::vector<AZStd::string> lineEntryData;
-                AzFramework::StringFunc::Tokenize(line.c_str(), lineEntryData, " ");
-                AZStd::string& fileName = lineEntryData.back();
-                
-                if(fileName.back() == AZ_CORRECT_FILESYSTEM_SEPARATOR)
-                {
-                    // if the filename ends with a separator
-                    // than it indicates that this is a directory
-                    continue;
-                }
-                
-                if(fileName.compare("-------") == 0)
-                {
-                    return;
-                }
-                
-                fileEntries.emplace_back(fileName);
-            }
-        }
-
-    } // namespace Platform
-} // namespace AzToolsFramework

+ 0 - 1
Code/Framework/AzToolsFramework/Platform/Mac/platform_mac_files.cmake

@@ -7,5 +7,4 @@
 #
 
 set(FILES
-    AzToolsFramework/Archive/ArchiveComponent_Mac.cpp
 )

+ 0 - 167
Code/Framework/AzToolsFramework/Platform/Windows/AzToolsFramework/Archive/ArchiveComponent_Windows.cpp

@@ -1,167 +0,0 @@
-/*
- * 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 <AzCore/std/string/string.h>
-#include <AzCore/Component/ComponentApplicationBus.h>
-#include <AzFramework/StringFunc/StringFunc.h>
-#include <AzToolsFramework/Archive/ArchiveComponent.h>
-
-namespace AzToolsFramework
-{
-    namespace Platform
-    {
-        const char CreateArchiveCmd[] = R"(a -tzip -mx=1 "%s" -r "%s\*")";
-
-        // -aos is for skipping extract on existing files
-        const char ExtractArchiveCmd[] = R"(x -mmt=off "%s" -o"%s\*" -aos)";
-        const char ExtractArchiveWithoutRootCmd[] = R"(x -mmt=off "%s" -o"%s" -aos)";
-        const char AddFilesCmd[] = R"(a -tzip "%s" @"%s")";
-        const char AddFileCmd[] = R"(a -tzip "%s" "%s")";
-        const char ExtractFileCmd[] = R"(e -mmt=off "%s" "%s" %s)";
-        const char ExtractFileDestination[] = R"(e -mmt=off "%s" -o"%s" "%s" %s)";
-        const char ExtractOverwrite[] = "-aoa";
-        const char ExtractSkipExisting[] = "-aos";
-        const char ListFilesInArchiveCmd[] = R"(l -r -slt "%s")";
-
-        AZStd::string Get7zExePath()
-        {
-            const char* rootPath = nullptr;
-            AZ::ComponentApplicationBus::BroadcastResult(rootPath, &AZ::ComponentApplicationRequests::GetEngineRoot);
-            AZStd::string exePath;
-            AzFramework::StringFunc::Path::ConstructFull(rootPath, "Tools", "7za", ".exe", exePath);
-            return exePath;
-        }
-
-        AZStd::string GetZipExePath()
-        {
-            return Get7zExePath();
-        }
-
-        AZStd::string GetUnzipExePath()
-        {
-            return Get7zExePath();
-        }
-
-        AZStd::string GetCreateArchiveCommand(const AZStd::string& archivePath, const AZStd::string& dirToArchive)
-        {
-            return AZStd::string::format(CreateArchiveCmd, archivePath.c_str(), dirToArchive.c_str());
-        }
-
-        AZStd::string GetExtractArchiveCommand(const AZStd::string& archivePath, const AZStd::string& destinationPath, bool includeRoot)
-        {
-            if (includeRoot)
-            {
-                // Extract archive path to destinationPath\<archiveFileName> and skipping extracting of existing files
-                return AZStd::string::format(ExtractArchiveCmd, archivePath.c_str(), destinationPath.c_str());
-            }
-            else
-            {
-                // Extract archive path to destinationPath and skipping extracting of existing files
-                return AZStd::string::format(ExtractArchiveWithoutRootCmd, archivePath.c_str(), destinationPath.c_str());
-            }
-        }
-
-        AZStd::string GetAddFilesToArchiveCommand(const AZStd::string& archivePath, const AZStd::string& listFilePath)
-        {
-            return AZStd::string::format(AddFilesCmd, archivePath.c_str(), listFilePath.c_str());
-        }
-
-        AZStd::string GetAddFileToArchiveCommand(const AZStd::string& archivePath, const AZStd::string& file)
-        {
-            return AZStd::string::format(AddFileCmd, archivePath.c_str(), file.c_str());
-        }
-
-        AZStd::string GetExtractFileCommand(const AZStd::string& archivePath, const AZStd::string& fileInArchive, const AZStd::string& destinationPath, bool overWrite)
-        {
-            AZStd::string commandLineArgs;
-            if (destinationPath.empty())
-            {
-                // Extract file in archive from archive path to the current directory, overwriting a file of the same name that exists there.
-                commandLineArgs = AZStd::string::format(ExtractFileCmd, archivePath.c_str(), fileInArchive.c_str(), overWrite ? ExtractOverwrite : ExtractSkipExisting);
-            }
-            else
-            {
-                // Extract file in archive from archive path to destinationPath, overwriting a file of the same name that exists there.
-                commandLineArgs = AZStd::string::format(ExtractFileDestination, archivePath.c_str(), destinationPath.c_str(), fileInArchive.c_str(), overWrite ? ExtractOverwrite : ExtractSkipExisting);
-            }
-
-            return commandLineArgs;
-        }
-
-        AZStd::string GetListFilesInArchiveCommand(const AZStd::string& archivePath)
-        {
-            AZStd::string commandLineArgs = AZStd::string::format(ListFilesInArchiveCmd, archivePath.c_str());
-            return commandLineArgs;
-        }
-
-    /*
-    File output for our list archive commands takes the following two patterns for files vs directories:
-
-    Path = basicfile2.txt
-    Folder = -
-    Size = 1
-    Packed Size = 1
-    Modified = 2019-03-26 18:31:10
-    Created = 2019-03-26 18:31:10
-    Accessed = 2019-03-26 18:31:10
-    Attributes = A
-    Encrypted = -
-    Comment =
-    CRC = 32D70693
-    Method = Store
-    Characteristics = NTFS
-    Host OS = FAT
-    Version = 10
-    Volume Index = 0
-    Offset = 44
-
-    Path = testfolder
-    Folder = +
-    Size = 0
-    Packed Size = 0
-    Modified = 2019-03-26 18:31:10
-    Created = 2019-03-26 18:31:10
-    Accessed = 2019-03-26 18:31:10
-    Attributes = D
-    Encrypted = -
-    Comment =
-    CRC =
-    Method = Store
-    Characteristics = NTFS
-    Host OS = FAT
-    Version = 20
-    Volume Index = 0
-    Offset = 89
-
-    */
-        
-        void ParseConsoleOutputFromListFilesInArchive(const AZStd::string& consoleOutput, AZStd::vector<AZStd::string>& fileEntries)
-        {
-            AZStd::vector<AZStd::string> fileEntryData;
-            AzFramework::StringFunc::Tokenize(consoleOutput.c_str(), fileEntryData, "\r\n");
-            for (size_t slotNum = 0; slotNum < fileEntryData.size(); ++slotNum)
-            {
-                AZStd::string& line = fileEntryData[slotNum];
-                if (AzFramework::StringFunc::StartsWith(line, "Path = "))
-                {
-                    if ((slotNum + 1) < fileEntryData.size())
-                    {
-                        // We're checking one past each entry we find for the Folder entry and skipping anything marked as a folder
-                        // See sample output above
-                        if (AzFramework::StringFunc::StartsWith(fileEntryData[slotNum + 1], "Folder = -"))
-                        {
-                            AzFramework::StringFunc::Replace(line, "Path = ", "", false, true);
-                            fileEntries.emplace_back(AZStd::move(line));
-                            slotNum++;
-                        }
-                    }
-                }
-            }
-        }
-    } // namespace Platform
-} // namespace AzToolsFramework

+ 0 - 1
Code/Framework/AzToolsFramework/Platform/Windows/platform_windows_files.cmake

@@ -7,5 +7,4 @@
 #
 
 set(FILES
-    AzToolsFramework/Archive/ArchiveComponent_Windows.cpp
 )

+ 104 - 22
Code/Framework/AzToolsFramework/Tests/ArchiveTests.cpp

@@ -31,7 +31,6 @@ namespace UnitTest
 {
     namespace
     {
-
         bool CreateDummyFile(const QString& fullPathToFile, const QString& tempStr = {})
         {
             QFileInfo fi(fullPathToFile);
@@ -50,7 +49,7 @@ namespace UnitTest
             return true;
         }
 
-        class ArchiveTest :
+        class ArchiveComponentTest :
             public ::testing::Test
         {
 
@@ -73,7 +72,12 @@ namespace UnitTest
                 return "Archive";
             }
 
-            void CreateArchiveFolder( QString archiveFolderName, QStringList fileList )
+            QString GetExtractFolderName()
+            {
+                return "Extracted";
+            }
+
+            void CreateArchiveFolder(QString archiveFolderName, QStringList fileList)
             {
                 QDir tempPath = QDir(m_tempDir.GetDirectory()).filePath(archiveFolderName);
 
@@ -84,6 +88,14 @@ namespace UnitTest
                 }
             }
 
+            QString CreateArchiveListTextFile()
+            {
+                QString listFilePath = QDir(m_tempDir.GetDirectory()).absoluteFilePath("FileList.txt");
+                QString textContent = CreateArchiveFileList().join("\n");
+                EXPECT_TRUE(CreateDummyFile(listFilePath, textContent));
+                return listFilePath;
+            }
+
             void CreateArchiveFolder()
             {
                 CreateArchiveFolder(GetArchiveFolderName(), CreateArchiveFileList());
@@ -99,16 +111,24 @@ namespace UnitTest
                 return QDir(m_tempDir.GetDirectory()).filePath(GetArchiveFolderName());
             }
 
+            QString GetExtractFolder()
+            {
+                return QDir(m_tempDir.GetDirectory()).filePath(GetExtractFolderName());
+            }
+
             bool CreateArchive()
             {
-                bool createResult{ false };
-                AzToolsFramework::ArchiveCommandsBus::BroadcastResult(createResult, &AzToolsFramework::ArchiveCommandsBus::Events::CreateArchiveBlocking, GetArchivePath().toStdString().c_str(), GetArchiveFolder().toStdString().c_str());
-                return createResult;
+                std::future<bool> createResult;
+                AzToolsFramework::ArchiveCommandsBus::BroadcastResult(createResult,
+                    &AzToolsFramework::ArchiveCommandsBus::Events::CreateArchive,
+                    GetArchivePath().toUtf8().constData(), GetArchiveFolder().toUtf8().constData());
+                bool result = createResult.get();
+                return result;
             }
 
             void SetUp() override
             {
-                m_app.reset(aznew ToolsTestApplication("ArchiveTest"));
+                m_app.reset(aznew ToolsTestApplication("ArchiveComponentTest"));
                 m_app->Start(AzFramework::Application::Descriptor());
                 // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
                 // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash 
@@ -132,76 +152,138 @@ namespace UnitTest
         };
 
 #if AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
-        TEST_F(ArchiveTest, DISABLED_CreateArchiveBlocking_FilesAtThreeDepths_ArchiveCreated)
+        TEST_F(ArchiveComponentTest, DISABLED_CreateArchive_FilesAtThreeDepths_ArchiveCreated)
 #else
-        TEST_F(ArchiveTest, CreateArchiveBlocking_FilesAtThreeDepths_ArchiveCreated)
+        TEST_F(ArchiveComponentTest, CreateArchive_FilesAtThreeDepths_ArchiveCreated)
 #endif // AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
         {
             EXPECT_TRUE(m_tempDir.IsValid());
             CreateArchiveFolder();
 
+            AZ_TEST_START_TRACE_SUPPRESSION;
             bool createResult = CreateArchive();
+            AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
 
-            EXPECT_EQ(createResult, true);
+            EXPECT_TRUE(createResult);
         }
 
 #if AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
-        TEST_F(ArchiveTest, DISABLED_ListFilesInArchiveBlocking_FilesAtThreeDepths_FilesFound)
+        TEST_F(ArchiveComponentTest, DISABLED_ListFilesInArchive_FilesAtThreeDepths_FilesFound)
 #else
-        TEST_F(ArchiveTest, ListFilesInArchiveBlocking_FilesAtThreeDepths_FilesFound)
+        TEST_F(ArchiveComponentTest, ListFilesInArchive_FilesAtThreeDepths_FilesFound)
 #endif // AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
         {
             EXPECT_TRUE(m_tempDir.IsValid());
             CreateArchiveFolder();
-            
+
+            AZ_TEST_START_TRACE_SUPPRESSION;
             EXPECT_EQ(CreateArchive(), true);
 
             AZStd::vector<AZStd::string> fileList;
             bool listResult{ false };
-            AzToolsFramework::ArchiveCommandsBus::BroadcastResult(listResult, &AzToolsFramework::ArchiveCommandsBus::Events::ListFilesInArchiveBlocking, GetArchivePath().toStdString().c_str(), fileList);
+            AzToolsFramework::ArchiveCommandsBus::BroadcastResult(listResult,
+                &AzToolsFramework::ArchiveCommandsBus::Events::ListFilesInArchive,
+                GetArchivePath().toUtf8().constData(), fileList);
+            AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
 
+            EXPECT_TRUE(listResult);
             EXPECT_EQ(fileList.size(), 6);
         }
 
 #if AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
-        TEST_F(ArchiveTest, DISABLED_CreateDeltaCatalog_AssetsNotRegistered_Failure)
+        TEST_F(ArchiveComponentTest, DISABLED_CreateDeltaCatalog_AssetsNotRegistered_Failure)
 #else
-        TEST_F(ArchiveTest, CreateDeltaCatalog_AssetsNotRegistered_Failure)
+        TEST_F(ArchiveComponentTest, CreateDeltaCatalog_AssetsNotRegistered_Failure)
 #endif // AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
         {
             QStringList fileList = CreateArchiveFileList();
 
             CreateArchiveFolder(GetArchiveFolderName(), fileList);
-
+            AZ_TEST_START_TRACE_SUPPRESSION;
             bool createResult = CreateArchive();
+            AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
 
             EXPECT_EQ(createResult, true);
 
             bool catalogCreated{ true };
             AZ::Test::AssertAbsorber assertAbsorber;
-            AzToolsFramework::AssetBundleCommandsBus::BroadcastResult(catalogCreated, &AzToolsFramework::AssetBundleCommandsBus::Events::CreateDeltaCatalog, GetArchivePath().toStdString().c_str(), true);
+            AzToolsFramework::AssetBundleCommandsBus::BroadcastResult(catalogCreated,
+                &AzToolsFramework::AssetBundleCommandsBus::Events::CreateDeltaCatalog, GetArchivePath().toUtf8().constData(), true);
 
             EXPECT_EQ(catalogCreated, false);
         }
 
 #if AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
-        TEST_F(ArchiveTest, DISABLED_CreateDeltaCatalog_ArchiveWithoutCatalogAssetsRegistered_Success)
+        TEST_F(ArchiveComponentTest, DISABLED_AddFilesToArchive_FromListFile_Success)
+#else
+        TEST_F(ArchiveComponentTest, AddFilesToArchive_FromListFile_Success)
+#endif // AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
+        {
+            QString listFile = CreateArchiveListTextFile();
+            CreateArchiveFolder(GetArchiveFolderName(), CreateArchiveFileList());
+
+            AZ_TEST_START_TRACE_SUPPRESSION;
+            std::future<bool> addResult;
+            AzToolsFramework::ArchiveCommandsBus::BroadcastResult(
+                addResult, &AzToolsFramework::ArchiveCommandsBus::Events::AddFilesToArchive, GetArchivePath().toUtf8().constData(),
+                GetArchiveFolder().toUtf8().constData(), listFile.toUtf8().constData());
+            bool result = addResult.get();
+            AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
+
+            EXPECT_TRUE(result);
+        }
+
+#if AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
+        TEST_F(ArchiveComponentTest, DISABLED_ExtractArchive_AllFiles_Success)
+#else
+        TEST_F(ArchiveComponentTest, ExtractArchive_AllFiles_Success)
+#endif // AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
+        {
+            CreateArchiveFolder();
+            AZ_TEST_START_TRACE_SUPPRESSION;
+            bool createResult = CreateArchive();
+            AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
+            EXPECT_TRUE(createResult);
+
+            AZ_TEST_START_TRACE_SUPPRESSION;
+            std::future<bool> extractResult;
+            AzToolsFramework::ArchiveCommandsBus::BroadcastResult(
+                extractResult, &AzToolsFramework::ArchiveCommandsBus::Events::ExtractArchive, GetArchivePath().toUtf8().constData(),
+                GetExtractFolder().toUtf8().constData());
+            bool result = extractResult.get();
+            AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
+
+            EXPECT_TRUE(result);
+
+            QStringList archiveFiles = CreateArchiveFileList();
+            for (const auto& file : archiveFiles)
+            {
+                QString fullFilePath = QDir(GetExtractFolder()).absoluteFilePath(file);
+                QFileInfo fi(fullFilePath);
+                EXPECT_TRUE(fi.exists());
+            }
+        }
+
+#if AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
+        TEST_F(ArchiveComponentTest, DISABLED_CreateDeltaCatalog_ArchiveWithoutCatalogAssetsRegistered_Success)
 #else
-        TEST_F(ArchiveTest, CreateDeltaCatalog_ArchiveWithoutCatalogAssetsRegistered_Success)
+        TEST_F(ArchiveComponentTest, CreateDeltaCatalog_ArchiveWithoutCatalogAssetsRegistered_Success)
 #endif // AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
         {
             QStringList fileList = CreateArchiveFileList();
 
             CreateArchiveFolder(GetArchiveFolderName(), fileList);
 
+            AZ_TEST_START_TRACE_SUPPRESSION;
             bool createResult = CreateArchive();
+            AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
 
             EXPECT_EQ(createResult, true);
 
             for (const auto& thisPath : fileList)
             {
                 AZ::Data::AssetInfo newInfo;
-                newInfo.m_relativePath = thisPath.toStdString().c_str();
+                newInfo.m_relativePath = thisPath.toUtf8().constData();
                 newInfo.m_assetType = AZ::Uuid::CreateRandom();
                 newInfo.m_sizeBytes = 100; // Arbitrary
                 AZ::Data::AssetId generatedID(AZ::Uuid::CreateRandom());
@@ -212,7 +294,7 @@ namespace UnitTest
 
             bool catalogCreated{ false };
             AZ_TEST_START_TRACE_SUPPRESSION;
-            AzToolsFramework::AssetBundleCommandsBus::BroadcastResult(catalogCreated, &AzToolsFramework::AssetBundleCommandsBus::Events::CreateDeltaCatalog, GetArchivePath().toStdString().c_str(), true);
+            AzToolsFramework::AssetBundleCommandsBus::BroadcastResult(catalogCreated, &AzToolsFramework::AssetBundleCommandsBus::Events::CreateDeltaCatalog, GetArchivePath().toUtf8().constData(), true);
             AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT; // produces different counts in different platforms
             EXPECT_EQ(catalogCreated, true);
         }

+ 1 - 1
Code/Framework/GridMate/GridMate/Carrier/Carrier.cpp

@@ -1316,7 +1316,7 @@ CarrierThread::CarrierThread(const CarrierDesc& desc, AZStd::shared_ptr<Compress
         {
             threadDesc.m_priority = desc.m_threadPriority;
         }
-        m_thread = AZStd::thread(AZStd::bind(&CarrierThread::ThreadPump, this), &threadDesc);
+        m_thread = AZStd::thread(threadDesc, AZStd::bind(&CarrierThread::ThreadPump, this));
     }
     else
     {

+ 1 - 1
Code/Framework/GridMate/GridMate/Carrier/SocketDriver.cpp

@@ -1694,7 +1694,7 @@ namespace GridMate
         //worker packet send thread
         AZStd::thread_desc workerSendThreadDesc;
         workerSendThreadDesc.m_name = "GridMate-Carrier Packet Send Thread";
-        m_workerSendThread = AZStd::thread(AZStd::bind(&SocketDriverCommon::RIOPlatformSocketDriver::WorkerSendThread, this), &workerSendThreadDesc);
+        m_workerSendThread = AZStd::thread(workerSendThreadDesc, AZStd::bind(&SocketDriverCommon::RIOPlatformSocketDriver::WorkerSendThread, this));
         if (m_workerSendThread.get_id() == AZStd::native_thread_invalid_id)
         {
             AZ_Error("GridMate", false, "Could not create worker thread.");

+ 2 - 1
Code/Tools/AssetBundler/source/models/SeedListTableModel.cpp

@@ -69,7 +69,8 @@ namespace AssetBundler
             assetInfo = AzToolsFramework::AssetSeedManager::GetAssetInfoById(
                 seed.m_assetId,
                 AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(seed.m_platformFlags)[0],
-                absolutePath);
+                absolutePath,
+                seed.m_assetRelativePath);
             platformList = QString(m_seedListManager->GetReadablePlatformList(seed).c_str());
 
             m_additionalSeedInfoMap[seed.m_assetId].reset(new AdditionalSeedInfo(assetInfo.m_relativePath.c_str(), platformList));

+ 1 - 1
Code/Tools/AssetProcessor/AssetBuilder/AssetBuilderComponent.cpp

@@ -411,7 +411,7 @@ bool AssetBuilderComponent::RunInResidentMode()
         m_running = true;
 
         m_jobThreadDesc.m_name = "Builder Job Thread";
-        m_jobThread = AZStd::thread(AZStd::bind(&AssetBuilderComponent::JobThread, this), &m_jobThreadDesc);
+        m_jobThread = AZStd::thread(m_jobThreadDesc, AZStd::bind(&AssetBuilderComponent::JobThread, this));
 
         AzFramework::EngineConnectionEvents::Bus::Handler::BusConnect(); // Listen for disconnects
 

+ 2 - 2
Code/Tools/AssetProcessor/native/tests/AssetCatalog/AssetCatalogUnitTests.cpp

@@ -1063,10 +1063,10 @@ namespace AssetProcessor
 
         AZStd::thread_desc threadDesc;
         threadDesc.m_name = "AssetCatalog Thread";
-        AZStd::thread catalogThread([this]()
+        AZStd::thread catalogThread(threadDesc, [this]()
             {
                 m_data->m_assetCatalog->BuildRegistry();
-            }, &threadDesc
+            }
         );
 
         AssetNotificationMessage message("some/path/image.png", AssetNotificationMessage::NotificationType::AssetChanged, AZ::Data::AssetType::CreateRandom(), "pc");

+ 16 - 8
Code/Tools/AssetProcessor/native/utilities/AssetServerHandler.cpp

@@ -74,8 +74,11 @@ namespace AssetProcessor
         AZ_TracePrintf(AssetProcessor::DebugChannel, "Extracting archive for job (%s, %s, %s) with fingerprint (%u).\n",
             builderParams.m_rcJob->GetJobEntry().m_pathRelativeToWatchFolder.toUtf8().data(), builderParams.m_rcJob->GetJobKey().toUtf8().data(),
             builderParams.m_rcJob->GetPlatformInfo().m_identifier.c_str(), builderParams.m_rcJob->GetOriginalFingerprint());
-        bool success = false;
-        AzToolsFramework::ArchiveCommands::Bus::BroadcastResult(success, &AzToolsFramework::ArchiveCommands::ExtractArchiveBlocking, archiveAbsFilePath.toUtf8().data(), builderParams.GetTempJobDirectory(), false);
+        std::future<bool> extractResult;
+        AzToolsFramework::ArchiveCommandsBus::BroadcastResult(extractResult,
+            &AzToolsFramework::ArchiveCommandsBus::Events::ExtractArchive,
+            archiveAbsFilePath.toUtf8().data(), builderParams.GetTempJobDirectory());
+        bool success = extractResult.get();
         AZ_Error(AssetProcessor::DebugChannel, success, "Extracting archive operation failed.\n");
         return success;
     }
@@ -106,12 +109,15 @@ namespace AssetProcessor
             return false;
         }
 
-        bool success = false;
-
         AZ_TracePrintf(AssetProcessor::DebugChannel, "Creating archive for job (%s, %s, %s) with fingerprint (%u).\n",
             builderParams.m_rcJob->GetJobEntry().m_pathRelativeToWatchFolder.toUtf8().data(), builderParams.m_rcJob->GetJobKey().toUtf8().data(),
             builderParams.m_rcJob->GetPlatformInfo().m_identifier.c_str(), builderParams.m_rcJob->GetOriginalFingerprint());
-        AzToolsFramework::ArchiveCommands::Bus::BroadcastResult(success, &AzToolsFramework::ArchiveCommands::CreateArchiveBlocking, archiveAbsFilePath.toUtf8().data(), builderParams.GetTempJobDirectory());
+
+        std::future<bool> createResult;
+        AzToolsFramework::ArchiveCommandsBus::BroadcastResult(createResult,
+            &AzToolsFramework::ArchiveCommandsBus::Events::CreateArchive,
+            archiveAbsFilePath.toUtf8().data(), builderParams.GetTempJobDirectory());
+        bool success = createResult.get();
         AZ_Error(AssetProcessor::DebugChannel, success, "Creating archive operation failed. \n");
 
         if (success && sourceFileList.size())
@@ -137,14 +143,16 @@ namespace AssetProcessor
                 allSuccess = false;
                 continue;
             }
-            bool success{ false };
-            AzToolsFramework::ArchiveCommands::Bus::BroadcastResult(success, &AzToolsFramework::ArchiveCommands::AddFileToArchiveBlocking, archivePath.toUtf8().data(), sourceDir.path().toUtf8().data(), thisProduct.c_str());
+            std::future<bool> addResult;
+            AzToolsFramework::ArchiveCommandsBus::BroadcastResult(addResult,
+                &AzToolsFramework::ArchiveCommandsBus::Events::AddFileToArchive,
+                archivePath.toUtf8().data(), sourceDir.path().toUtf8().data(), thisProduct.c_str());
+            bool success = addResult.get();
             if (!success)
             {
                 AZ_Warning(AssetProcessor::DebugChannel, false, "Failed to add %s to %s", thisProduct.c_str(), archivePath.toUtf8().data());
                 allSuccess = false;
             }
-
         }
         return allSuccess;
     }

+ 1 - 1
Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp

@@ -99,7 +99,7 @@ void SRemoteThreadedObject::Start(const char* name)
     desc.m_name = name;
 
     auto function = AZStd::bind(&SRemoteThreadedObject::ThreadFunction, this);
-    m_thread = AZStd::thread(function, &desc);
+    m_thread = AZStd::thread(desc, function);
 }
 
 void SRemoteThreadedObject::WaitForThread()

+ 1 - 1
Gems/Atom/RHI/Code/Source/RHI/AsyncWorkQueue.cpp

@@ -26,7 +26,7 @@ namespace AZ
             m_workItemIndex = 0;
             m_lastCompletedWorkItem = AsyncWorkHandle::Null;
             AZStd::thread_desc threadDesc{ "AsyncWorkQueue" };
-            m_thread = AZStd::thread([&]() { ProcessQueue(); }, &threadDesc);
+            m_thread = AZStd::thread(threadDesc, [&]() { ProcessQueue(); });
             m_isInitialized = true;
         }
 

+ 1 - 1
Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp

@@ -43,7 +43,7 @@ namespace AZ
                 m_isWorkQueueEmpty = true;
                 
                 AZStd::thread_desc threadDesc{ GetName().GetCStr() };
-                m_thread = AZStd::thread([&]() { ProcessQueue(); }, &threadDesc);
+                m_thread = AZStd::thread(threadDesc, [&]() { ProcessQueue(); });
             }
             return resultCode;
         }

+ 2 - 2
Gems/Atom/RHI/Code/Source/RHI/Fence.cpp

@@ -108,7 +108,7 @@ namespace AZ
 
             AZStd::thread_desc threadDesc{ "Fence WaitOnCpu Thread" };
 
-            m_waitThread = AZStd::thread([this, callback]()
+            m_waitThread = AZStd::thread(threadDesc, [this, callback]()
             {
                 ResultCode resultCode = WaitOnCpu();
                 if (resultCode != ResultCode::Success)
@@ -116,7 +116,7 @@ namespace AZ
                     AZ_Error("Fence", false, "Failed to call WaitOnCpu in async thread.");
                 }
                 callback();
-            }, &threadDesc);
+            });
 
             return ResultCode::Success;
         }

+ 2 - 3
Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp

@@ -24,12 +24,11 @@ namespace AZ
             threadDesc.m_name = "ShaderVariantAsyncLoader";
 
             m_serviceThread = AZStd::thread(
+                threadDesc,
                 [this]()
                 {
                     this->ThreadServiceLoop();
-                },
-                &threadDesc
-                    );
+                });
         }
 
         void ShaderVariantAsyncLoader::ThreadServiceLoop()

+ 1 - 1
Gems/AudioSystem/Code/Source/Engine/AudioSystem.cpp

@@ -56,7 +56,7 @@ namespace Audio
         threadDesc.m_cpuId = AZ_TRAIT_AUDIOSYSTEM_AUDIO_THREAD_AFFINITY;
 
         auto threadFunc = AZStd::bind(&CAudioThread::Run, this);
-        m_thread = AZStd::thread(threadFunc, &threadDesc);
+        m_thread = AZStd::thread(threadDesc, threadFunc);
     }
 
     ///////////////////////////////////////////////////////////////////////////////////////////////////

+ 1 - 1
Gems/BarrierInput/Code/Source/BarrierInputClient.cpp

@@ -347,7 +347,7 @@ namespace BarrierInput
     {
         AZStd::thread_desc threadDesc;
         threadDesc.m_name = "BarrierInputClientThread";
-        m_threadHandle = AZStd::thread(AZStd::bind(&BarrierClient::Run, this), &threadDesc);
+        m_threadHandle = AZStd::thread(threadDesc, AZStd::bind(&BarrierClient::Run, this));
     }
     
     ////////////////////////////////////////////////////////////////////////////////////////////////

+ 1 - 1
Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp

@@ -37,7 +37,7 @@ namespace HttpRequestor
         m_runThread = true;
         AWSNativeSDKInit::InitializationManager::InitAwsApi();
         auto function = AZStd::bind(&Manager::ThreadFunction, this);
-        m_thread = AZStd::thread(function, &desc);
+        m_thread = AZStd::thread(desc, function);
     }
 
     Manager::~Manager()

+ 9 - 26
Gems/LmbrCentral/Code/Source/Builders/LevelBuilder/LevelBuilderWorker.cpp

@@ -12,6 +12,7 @@
 #include <AzCore/Component/ComponentApplicationBus.h>
 #include <AzCore/Component/TickBus.h>
 #include <AzCore/Debug/Trace.h>
+#include <AzCore/IO/Path/Path.h>
 #include <AzCore/IO/SystemFile.h>
 #include <AzCore/Slice/SliceAsset.h>
 #include <AzCore/Slice/SliceAssetHandler.h>
@@ -155,35 +156,17 @@ namespace LevelBuilder
     {
         PopulateOptionalLevelDependencies(sourceRelativeFile, productPathDependencies);
 
-        AZStd::binary_semaphore extractionCompleteSemaphore;
-        auto extractResponseLambda = [&]([[maybe_unused]] bool success) {
-            AZStd::string levelsubfolder;
-            AzFramework::StringFunc::Path::Join(tempDirectory.c_str(), "level", levelsubfolder);
+        std::future<bool> extractResult;
+        AzToolsFramework::ArchiveCommandsBus::BroadcastResult(
+            extractResult, &AzToolsFramework::ArchiveCommandsBus::Events::ExtractArchive, levelPakFile, tempDirectory);
 
-            PopulateLevelSliceDependencies(levelsubfolder, productDependencies, productPathDependencies);
-            PopulateMissionDependencies(levelPakFile, levelsubfolder, productPathDependencies);
-            PopulateLevelAudioControlDependencies(levelPakFile, productPathDependencies);
+        extractResult.wait();
 
-            extractionCompleteSemaphore.release();
-        };
+        auto levelsubfolder = AZ::IO::Path(tempDirectory) / "level";
 
-        AZ::Uuid handle = AZ::Uuid::Create();
-        AzToolsFramework::ArchiveCommands::Bus::Broadcast(
-            &AzToolsFramework::ArchiveCommands::ExtractArchive,
-            levelPakFile,
-            tempDirectory,
-            handle,
-            extractResponseLambda);
-
-        const int archiveExtractSleepMS = 20;
-        bool extractionCompleted = false;
-        while (!extractionCompleted)
-        {
-            extractionCompleted = extractionCompleteSemaphore.try_acquire_for(AZStd::chrono::milliseconds(archiveExtractSleepMS));
-            // When the archive extraction is completed, the response lambda is queued on the the tick bus.
-            // This loop will keep executing queued events on the tickbus until the response unlocks the semaphore.
-            AZ::TickBus::ExecuteQueuedEvents();
-        }
+        PopulateLevelSliceDependencies(levelsubfolder.Native(), productDependencies, productPathDependencies);
+        PopulateMissionDependencies(levelPakFile, levelsubfolder.Native(), productPathDependencies);
+        PopulateLevelAudioControlDependencies(levelPakFile, productPathDependencies);
     }
 
     AZStd::string GetLastFolderFromPath(const AZStd::string& path)

+ 1 - 1
Gems/Microphone/Code/Source/Platform/Windows/MicrophoneSystemComponent_Windows.cpp

@@ -225,7 +225,7 @@ namespace Audio
             AZStd::thread_desc threadDesc;
             threadDesc.m_name = "MicrophoneCapture-WASAPI";
             auto captureFunc = AZStd::bind(&MicrophoneSystemComponentWindows::RunAudioCapture, this);
-            m_captureThread = AZStd::thread(captureFunc, &threadDesc);
+            m_captureThread = AZStd::thread(threadDesc, captureFunc);
 
             return true;
         }

+ 1 - 1
Gems/PhysX/Code/Tests/PhysXMultithreadingTest.cpp

@@ -119,7 +119,7 @@ namespace PhysX
         void Start(int waitTimeMilliseconds)
         {
             m_waitTimeMilliseconds = waitTimeMilliseconds;
-            m_thread = AZStd::thread(AZStd::bind(&SceneQueryBase::Tick, this), &m_threadDesc);
+            m_thread = AZStd::thread(m_threadDesc, AZStd::bind(&SceneQueryBase::Tick, this));
         }
 
         void Join()

+ 15 - 13
Gems/SaveData/Code/Source/SaveDataSystemComponent.cpp

@@ -172,14 +172,15 @@ namespace SaveData
 
         // This is safe access outside the lock guard because we only remove elements from the list
         // after the thread completion flag has been set to true (see also JoinAllCompletedThreads).
-        threadCompletionPair->m_thread = AZStd::make_unique<AZStd::thread>([&threadCompleteFlag = threadCompletionPair->m_threadComplete,
-                                                                            dataBuffer = AZStd::move(saveDataBufferParams.dataBuffer),
-                                                                            dataBufferSize = saveDataBufferParams.dataBufferSize,
-                                                                            dataBufferName = saveDataBufferParams.dataBufferName,
-                                                                            onSavedCallback = saveDataBufferParams.callback,
-                                                                            localUserId = saveDataBufferParams.localUserId,
-                                                                            absoluteFilePath,
-                                                                            useTemporaryFile]()
+        threadCompletionPair->m_thread = AZStd::make_unique<AZStd::thread>(saveThreadDesc,
+                                                                           [&threadCompleteFlag = threadCompletionPair->m_threadComplete,
+                                                                           dataBuffer = AZStd::move(saveDataBufferParams.dataBuffer),
+                                                                           dataBufferSize = saveDataBufferParams.dataBufferSize,
+                                                                           dataBufferName = saveDataBufferParams.dataBufferName,
+                                                                           onSavedCallback = saveDataBufferParams.callback,
+                                                                           localUserId = saveDataBufferParams.localUserId,
+                                                                           absoluteFilePath,
+                                                                           useTemporaryFile]()
         {
             SaveDataNotifications::Result result = SaveDataNotifications::Result::ErrorUnspecified;
 
@@ -234,7 +235,7 @@ namespace SaveData
 
             // Set the thread completion flag so it will be joined in JoinAllCompletedThreads.
             threadCompleteFlag = true;
-        }, &saveThreadDesc);
+        });
 
         if (waitForCompletion)
         {
@@ -301,9 +302,10 @@ namespace SaveData
 
         // This is safe access outside the lock guard because we only remove elements from the list
         // after the thread completion flag has been set to true (see also JoinAllCompletedThreads).
-        threadCompletionPair->m_thread = AZStd::make_unique<AZStd::thread>([&threadCompleteFlag = threadCompletionPair->m_threadComplete,
-                                                                            loadDataBufferParams,
-                                                                            absoluteFilePath]()
+        threadCompletionPair->m_thread = AZStd::make_unique<AZStd::thread>(loadThreadDesc,
+                                                                           [&threadCompleteFlag = threadCompletionPair->m_threadComplete,
+                                                                           loadDataBufferParams,
+                                                                           absoluteFilePath]()
         {
             SaveDataNotifications::DataBuffer dataBuffer = nullptr;
             AZ::u64 dataBufferSize = 0;
@@ -352,7 +354,7 @@ namespace SaveData
 
             // Set the thread completion flag so it will be joined in JoinAllCompletedThreads.
             threadCompleteFlag = true;
-        }, &loadThreadDesc);
+        });
 
         if (waitForCompletion)
         {

+ 0 - 3
Tools/7za.exe

@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:77613cca716edf68b9d5bab951463ed7fade5bc0ec465b36190a76299c50f117
-size 733696

+ 0 - 36
Tools/7za_legal_notice.txt

@@ -1,36 +0,0 @@
-Amazon note:  Source for 7-zip is hosted at 
-https://s3-us-west-2.amazonaws.com/ly-legal/LicenseConformance/7-zip/18.05/7z1805-src.7z
-
-
-
-      7-Zip Extra
-      ~~~~~~~~~~~
-      License for use and distribution
-      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-      Copyright (C) 1999-2015 Igor Pavlov.
-
-      7-Zip Extra files are under the GNU LGPL license.
-
-      
-      Notes: 
-        You can use 7-Zip Extra on any computer, including a computer in a commercial 
-        organization. You don't need to register or pay for 7-Zip.
-
-
-      GNU LGPL information
-      --------------------
-
-        This library is free software; you can redistribute it and/or
-        modify it under the terms of the GNU Lesser General Public
-        License as published by the Free Software Foundation; either
-        version 2.1 of the License, or (at your option) any later version.
-
-        This library is distributed in the hope that it will be useful,
-        but WITHOUT ANY WARRANTY; without even the implied warranty of
-        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-        Lesser General Public License for more details.
-
-        You can receive a copy of the GNU Lesser General Public License from 
-        http://www.gnu.org/
-