Kaynağa Gözat

Integrating latest from github/staging
Integrating up through commit 5e1bdae

alexpete 4 yıl önce
ebeveyn
işleme
36c4e827bd
100 değiştirilmiş dosya ile 2012 ekleme ve 4646 silme
  1. 0 30
      .p4ignore
  2. 0 590
      AssetProcessorPlatformConfig.ini
  3. 224 15
      AssetProcessorPlatformConfig.setreg
  4. 66 45
      AutomatedReview/Jenkinsfile
  5. 8 0
      AutomatedTesting/CMakeLists.txt
  6. 0 197
      AutomatedTesting/Config/Editor.xml
  7. 0 179
      AutomatedTesting/Config/Game.xml
  8. 0 136
      AutomatedTesting/Config/Server.xml
  9. 0 16
      AutomatedTesting/Gem/AssetProcessorGemConfig.ini
  10. 23 0
      AutomatedTesting/Gem/AssetProcessorGemConfig.setreg
  11. 36 4
      AutomatedTesting/Gem/PythonTests/CMakeLists.txt
  12. 6 6
      AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_all_platforms_setup_fixture.py
  13. 1 1
      AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_external_project_setup_fixture.py
  14. 3 2
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests_2.py
  15. 15 19
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests_2.py
  16. 1 1
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/missing_dependency_tests.py
  17. 2 2
      AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/fbx_tests.py
  18. 3 2
      AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py
  19. 2 8
      AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Active.py
  20. 30 0
      AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Sandbox.py
  21. 36 6
      AutomatedTesting/Registry/assets_scan_folders.setreg
  22. 4 1
      AutomatedTesting/TestAssets/test_chunks_builder.py
  23. 1 1
      AutomatedTesting/UI/TextureAtlas/sample.texatlas
  24. 0 298
      AutomatedTesting/gems.json
  25. 2 2
      BuildReleaseAuxiliaryContent.py
  26. 22 5
      CMakeLists.txt
  27. 1 1
      Code/CryEngine/Cry3DEngine/3DEngineRender.cpp
  28. 1 1
      Code/CryEngine/Cry3DEngine/3dEngine.cpp
  29. 2 12
      Code/CryEngine/Cry3DEngine/3dEngineLoad.cpp
  30. 2 1
      Code/CryEngine/Cry3DEngine/LightEntity.cpp
  31. 1 14
      Code/CryEngine/Cry3DEngine/Material.cpp
  32. 1 14
      Code/CryEngine/Cry3DEngine/Material.h
  33. 1 9
      Code/CryEngine/Cry3DEngine/StatObj.h
  34. 0 4
      Code/CryEngine/Cry3DEngine/StatObjConstr.cpp
  35. 1 1
      Code/CryEngine/CryCommon/IAudioSystem.h
  36. 1 6
      Code/CryEngine/CryCommon/IMaterial.h
  37. 7 189
      Code/CryEngine/CryCommon/ISystem.h
  38. 7 8
      Code/CryEngine/CryCommon/MaterialUtils.h
  39. 0 18
      Code/CryEngine/CryCommon/Mocks/ISystemMock.h
  40. 0 160
      Code/CryEngine/CryCommon/ParseEngineConfig.h
  41. 1 1
      Code/CryEngine/CryCommon/ProjectDefines.h
  42. 0 1
      Code/CryEngine/CryCommon/crycommon_files.cmake
  43. 0 630
      Code/CryEngine/CrySystem/BootProfiler.cpp
  44. 0 67
      Code/CryEngine/CrySystem/BootProfiler.h
  45. 1 12
      Code/CryEngine/CrySystem/DebugCallStack.cpp
  46. 7 11
      Code/CryEngine/CrySystem/IDebugCallStack.cpp
  47. 0 647
      Code/CryEngine/CrySystem/LoadingProfiler.cpp
  48. 0 69
      Code/CryEngine/CrySystem/LoadingProfiler.h
  49. 4 6
      Code/CryEngine/CrySystem/NotificationNetwork.cpp
  50. 1 1
      Code/CryEngine/CrySystem/StreamEngine/StreamEngine.cpp
  51. 12 28
      Code/CryEngine/CrySystem/System.cpp
  52. 3 33
      Code/CryEngine/CrySystem/System.h
  53. 3 9
      Code/CryEngine/CrySystem/SystemCFG.cpp
  54. 44 297
      Code/CryEngine/CrySystem/SystemInit.cpp
  55. 0 15
      Code/CryEngine/CrySystem/SystemWin32.cpp
  56. 0 115
      Code/CryEngine/CrySystem/Tests/Test_BootProfiler.cpp
  57. 5 10
      Code/CryEngine/CrySystem/Tests/test_MaterialUtils.cpp
  58. 2 2
      Code/CryEngine/CrySystem/UnitTests/CryPakUnitTests.cpp
  59. 2 2
      Code/CryEngine/CrySystem/VisRegTest.cpp
  60. 0 4
      Code/CryEngine/CrySystem/crysystem_files.cmake
  61. 2 2
      Code/CryEngine/RenderDll/Common/Renderer.cpp
  62. 10 12
      Code/CryEngine/RenderDll/Common/Shaders/RemoteCompiler.cpp
  63. 99 32
      Code/CryEngine/RenderDll/Common/Shaders/RemoteShaderCompilerUnitTests.cpp
  64. 4 3
      Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp
  65. 1 1
      Code/CryEngine/RenderDll/Common/Shaders/ShaderCore.cpp
  66. 1 1
      Code/CryEngine/RenderDll/Common/Shaders/ShaderSerialize.cpp
  67. 2 2
      Code/CryEngine/RenderDll/XRenderD3D9/D3DHWShaderCompiling.cpp
  68. 3 2
      Code/CryEngine/RenderDll/XRenderD3D9/D3DSystem.cpp
  69. 209 117
      Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
  70. 32 34
      Code/Framework/AzCore/AzCore/Component/ComponentApplication.h
  71. 5 0
      Code/Framework/AzCore/AzCore/Component/ComponentApplicationBus.h
  72. 4 2
      Code/Framework/AzCore/AzCore/Console/Console.cpp
  73. 14 25
      Code/Framework/AzCore/AzCore/IO/FileIO.h
  74. 4 4
      Code/Framework/AzCore/AzCore/IO/Path/Path.h
  75. 3 3
      Code/Framework/AzCore/AzCore/IO/Path/Path.inl
  76. 1 0
      Code/Framework/AzCore/AzCore/Math/MathReflection.cpp
  77. 53 0
      Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp
  78. 12 0
      Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.h
  79. 186 122
      Code/Framework/AzCore/AzCore/Settings/CommandLine.cpp
  80. 37 14
      Code/Framework/AzCore/AzCore/Settings/CommandLine.h
  81. 9 1
      Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp
  82. 400 229
      Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp
  83. 59 24
      Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h
  84. 52 28
      Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp
  85. 47 4
      Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h
  86. 1 0
      Code/Framework/AzCore/AzCore/UnitTest/MockComponentApplication.h
  87. 1 0
      Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockFileIOBase.h
  88. 43 0
      Code/Framework/AzCore/AzCore/Utils/Utils.cpp
  89. 16 5
      Code/Framework/AzCore/AzCore/Utils/Utils.h
  90. 5 0
      Code/Framework/AzCore/AzCore/std/string/fixed_string.h
  91. 17 0
      Code/Framework/AzCore/AzCore/std/string/fixed_string.inl
  92. 16 0
      Code/Framework/AzCore/AzCore/std/string/string.h
  93. 16 0
      Code/Framework/AzCore/AzCore/std/string/string_view.h
  94. 5 5
      Code/Framework/AzCore/Platform/Android/AzCore/Utils/Utils_Android.cpp
  95. 1 0
      Code/Framework/AzCore/Platform/Android/platform_android_files.cmake
  96. 22 0
      Code/Framework/AzCore/Platform/Common/Unimplemented/AzCore/Utils/Utils_Unimplemented.cpp
  97. 19 4
      Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/Utils/Utils_UnixLike.cpp
  98. 4 4
      Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp
  99. 1 1
      Code/Framework/AzCore/Platform/Linux/AzCore/Utils/Utils_Linux.cpp
  100. 1 1
      Code/Framework/AzCore/Platform/Mac/AzCore/Utils/Utils_Mac.cpp

+ 0 - 30
.p4ignore

@@ -1,30 +0,0 @@
-*.ilk
-*.suo
-*.user
-*.o
-*.temp
-*.bootstrap.digests
-*.log
-*.exp
-*.vssettings
-*.exportlog
-*.mayaSwatches
-*.ma.swatches
-*.bak
-*.bak2
-*.akd
-Solutions
-BinTemp
-*.options
-*.pyc
-*.db
-Cache
-AssetProcessor_tmp.exe
-Builders_Temp
-Bin64vc*
-$tmp*
-.pytest_cache
-__pycache__
-# Python Module egg file
-*.egg
-*.egg-link

+ 0 - 590
AssetProcessorPlatformConfig.ini

@@ -1,590 +0,0 @@
-; ---- Enable/Disable platforms for the entire project. AssetProcessor will automatically add the current platform by default. 
-
-; PLATFORM DEFINITIONS
-; [Platform (unique identifier)]
-; tags=(comma-seperated-tags)
-;
-; note:  the 'identifier' of a platform is the word(s) following the "Platform" keyword (so [Platform pc] means identifier
-;        is 'pc' for example.  This is used to name its assets folder in the cache and should be used in your bootstrap.cfg
-;        or your main.cpp to choose what assets to load for that particular platform.
-;        Its primary use is to enable additional non-host platforms (Ios, android...) that are not the current platform.
-; note:  'tags' is a comma-seperated list of tags to tag the platform with that builders can inspect to decide what to do.
-
-; while builders can accept any tags you add in order to make decisions, common tags are
-; tools - this platform can host the tools and editor and such
-; renderer - this platform runs the client engine and renders on a GPU.  If missing we could be on a server-only platform
-; mobile - a mobile platform such as a set top box or phone with limited resources
-; console - a console platform
-; server - a server platform of some kind, usually headless, no renderer.
-
-[Platform pc]
-tags=tools,renderer,dx12,vulkan
-
-[Platform es3]
-tags=android,mobile,renderer,vulkan
-
-[Platform ios]
-tags=mobile,renderer,metal
-
-[Platform osx_gl]
-tags=tools,renderer,metal
-
-; this is an example of a headless platform that has no renderer.   
-; To use this you would still need to make sure 'assetplatform' in your startup params in your main() chooses this 'server' platform as your server 'assets' flavor
-[Platform server]
-tags=server,dx12,vulkan
-
-; this section allows you to turn on various platforms in addition to the host platform you're running on
-; 'enabled' is AUTOMATICALLY TRUE for the current platform that you are running on, so it is not necessary to force it to true for that platform
-; To enable any additional platform, just uncomment the appropriate line below.
-
-[Platforms]
-;pc=enabled
-;es3=enabled
-;ios=enabled
-;osx_gl=enabled
-;jasper=enabled
-;provo=enabled
-;salem=enabled
-;server=enabled
-
-; ---- The number of worker jobs, 0 means use the number of Logical Cores
-[Jobs]
-minJobs=1
-maxJobs=0
-
-; cacheServerAddress is the location of the asset server cache.
-; Currently for a network share server this would be the absolute file path to the network share folder.  
-[Server]
-;cacheServerAddress=
-
-; ---- add any metadata file type here that needs to be monitored by the AssetProcessor.
-; Modifying these meta file will cause the source asset to re-compile again.
-; They are specified in the following format
-; metadata extension=original extension to replace
-; if the metadata extension does not replace the original, then the original can be blank
-; so for example if your normal file is blah.tif and your metafile for that file is blah.tif.exportsettings
-; then your declaration would be exportsettings=   ; ie, it would be blank
-; however if your metafile REPLACES the extension (for example, if you have the file blah.i_caf and its metafile is blah.exportsettings)
-; then you specify the original extension here to narrow the scope.
-; If a relative path to a specific file is provided instead of an extension, a change to the file will change all files
-; with the associated extension (e.g. Animations/SkeletonList.xml=i_caf will cause all i_caf files to recompile when 
-; Animations/SkeletonList.xml within the current game project changes)
-
-[MetaDataTypes]
-exportsettings=
-animsettings=i_caf
-Animations/SkeletonList.xml=i_caf
-cbc=abc
-fbx.assetinfo=fbx
-
-; ---- add any folders to scan here.  The priority order is the order they appear here
-; available macros are 
-; @ROOT@ - the location of engineroot.txt
-; @GAMENAME@ - the name of the current game project, for example 'RPGSample' 
-; note that they are sorted by their 'order' value, and the lower the order the more important an asset is
-; lower order numbers override higher ones.
-; If specified, output will be prepended to every path found in that recognizer's watch folder.
-; Note that you can also make the scan folder platform specific by using the keywords include and exclude.
-; Both include and exclude can contain either platform tags, platform identifiers or both.
-; if no include is specified, all currently enabled platforms are included by default.
-; If includes ARE specified, it will be filtered down by the list of currently enabled platforms. 
-; [ScanFolder (unique identifier)]
-; include = (comma seperated platform tags or identifiers)
-; exclude = (comma seperated platform tags or identifiers)
-; For example if you want to include a scan folder only for platforms that have the platform tags tools and renderer 
-; but omit it for platform osx_gl, you will have a scanfolder rule like
-; [ScanFolder (unique identifier)]
-; watch=@ROOT@/foo
-; include = tools, renderer
-; exclude = osx_gl 
-
-[ScanFolder Game]
-watch=@ROOT@/@GAMENAME@
-display=@GAMENAME@
-recursive=1
-order=0
-
-; gems will be auto-added from 100 onwards
-
-[ScanFolder Root]
-watch=@ROOT@
-recursive=0
-order=10000
-
-[ScanFolder Engine]
-watch=@ENGINEROOT@/Engine
-recursive=1
-order=20000
-
-[ScanFolder Editor]
-watch=@ENGINEROOT@/Editor
-output=editor
-recursive=1
-order=30000
-include=tools,renderer
-
-
-;Excludes files that match the pattern or glob 
-; if you use a pattern, remember to escape your backslashes (\\)
-[Exclude _LevelBackups]
-pattern=.*\\/Levels\\/.*\\/_savebackup\\/.*
-
-[Exclude _LevelAutoBackups]
-pattern=.*\\/Levels\\/.*\\/_autobackup\\/.*
-
-[Exclude HoldFiles]
-pattern=.*\\/Levels\\/.*_hold\\/.*
-
-[Exclude TempFiles]
-; note that $ has meaning to regex, so we escape it.
-pattern=.*\\/\\$tmp[0-9]*_.*
-
-[Exclude AlembicCompressionTemplates]
-pattern=.*\\/Presets\\/GeomCache\\/.*
-
-[Exclude TmpAnimationCompression]
-pattern=.*\\/Editor\\/Tmp\\/AnimationCompression\\/.*
-
-[Exclude EventLog]
-pattern=.*\\/Editor\\/.*eventlog\\.xml
-
-[Exclude GameGemsCode]
-pattern=.*\\/Gem\\/Code\\/.*
-
-[Exclude GameGemsResources]
-pattern=.*\\/Gem\\/Resources\\/.*
-
-[Exclude Private Certs]
-pattern=.*\DynamicContent\\/Certificates\\/Private\\/.*
-
-[Exclude CMakeLists]
-pattern=.*\\/CMakeLists.txt
-
-[Exclude CMakeFiles]
-pattern=.*\\/.*\\.cmake
-
-;------------------------------------------------------------------------------
-; Large Worlds Test
-;------------------------------------------------------------------------------
-
-[Exclude Work In Progress Folders]
-pattern=.*\\/WIP\\/.*
-
-[Exclude Content Source Folders]
-pattern=.*\\/CONTENT_SOURCE\\/.*
-
-[Exclude Art Source Folders]
-pattern=.*\\/ArtSource\\/.*
-
-;------------------------------------------------------------------------------
-; RC params mapping examples
-;------------------------------------------------------------------------------
-
-; note that productAssetType is a means of setting the output asset Type (as in AZ::Data::AssetType) of a simple job
-; and is the recommended way to specify that a certain kind of file (such as '*.myextension') becomes registered as the
-; actual UUID of that type in the engine itself.
-
-; Use a regex for matching files, same params for all platforms
-;[RC TGAs]
-;pattern=.+\\.tga$
-;params=/tga /texture
-
-; Use a glob, have special params for es3 platform
-;[RC TIFFs]
-;glob=*.tif
-;params=/texture
-;es3=/pvrt
-
-; You can also modify a version to compile all matching files again
-; By default the version is empty
-;[RC tif]
-;glob=*.tif
-;params = \\someparams
-;version =1.0
-; This will make the AssetProcessor compile all the .tif files again
-
-; you can also optionally supply a priority.
-; this is used to sort jobs when no other external circumstance sorts them
-; for example, copy jobs will be higher in priority than other jobs that are not copy jobs
-; however if they're both copy jobs or both not, and no other circumstances apply, then priority will be used.
-; default priority is zero if not specified
-
-; you can specify an option to skip processing for a file type based on the platform.
-; for example, if you dont want to process tif files for ios, you can make tif files
-; process on any platform except for ios:
-;[RC tif]
-;glob=*.tif
-;params = \\someparams
-;ios=skip
-
-; you can specify an option to output product dependencies for a copy job.
-; please note that you only need to set this option when cry code is required to parse the asset.
-; otherwise product dependencies will be output automatically by the CopyDependencyBuilder.
-; for example, if you want to output the product dependencies for font assets:
-;[RC font]
-;glob=*.font
-;params=copy
-;outputProductDependencies=true
-
-; you can also specify an option to make all jobs critical that matches some pattern/glob.
-; for example, if you want to make all png files critical than set critical to true.
-; Note that by default all copy jobs are critical.
-; Critical jobs are processed before non critical jobs and also prevent the runtime or editor from starting until they are all complete.
-;[RC png]
-;glob=*.png
-;params = \\someparams
-;critical=true
-
-; you can also specify an option to make all the job store in the asset server cache location if you are running AP in server mode. 
-; For example, if you want to store all png jobs in the asset server cache location including their logs, you can set checkServer = true.
-; The client(i.e if you are running AP in non-server mode) will also check for this flag to know which jobs to fetch from the asset server cache location.
-; if unsucessful, it will process the job locally as usual.
-;[RC png]
-;glob=*.png
-;params = \\someparams
-;critical=true
-;checkServer=true
-
-; note that the FULL PATH to the file will be used as the match, not the relative path
-; so ensure start your patterns with .* or as appropriate.
-; Also, any rules which match will apply - so if you have two rules which both apply to PNG files for example
-; but you only want one, you might want to use exclusion patterns:
- 
-;Example: process everything EXCEPT the ones in the libs/ui folder with these params
-;[RC png-normal]
-;pattern=(?!.*libs\\/ui\\/).*\\.png
-;params=/imagecompressor=CTSquish /streaming=0
-;lockSource=true
-
-;Example:  Process everything in the libs/ui folder with linear color space
-;[RC png-ui]
-;pattern=(.*libs\\/ui\\/).*\\.png
-;params=/imagecompressor=CTSquish /streaming=0 /colorspace=linear,linear
-;lockSource=true
-
-; More example Regexes:
-; pattern=(?!(.*libs\\/ui\\/)|(.*editor\\/).*\\.png
-; This pattern will not match anything with editor/ or libs/ui/ in it
-; pattern=((.*libs\\/ui\\/)|(.*editor\\/).*\\.png
-; This pattern will only match anything with editor/ or libs/ui/ in it
-
-;Give every [Section Name] its own unique Name or else they will overwrite each other!
-
-[RC i_caf]
-glob=*.i_caf
-params=/cafAlignTracks=1 /animConfigFolder=Animations /skipdba=1 /refresh=1
-; force server to send the 'pc' platform to RC.EXE so it compiles the same as PC.
-server=/cafAlignTracks=1 /animConfigFolder=Animations /skipdba=1 /refresh=1 /p=pc
-priority=5
-productAssetType={6023CFF8-FCBA-4528-A8BF-6E0E10B9AB9C}
-
-[RC caf]
-glob=*.caf
-params=copy
-productAssetType={6023CFF8-FCBA-4528-A8BF-6E0E10B9AB9C}
-; same as above
-
-[RC mp4]
-glob=*.mp4
-params=copy
-productAssetType={DDFEE0B2-9E5A-412C-8C77-AB100E24C1DF}
-
-[RC mkv]
-glob=*.mkv
-params=copy
-productAssetType={DDFEE0B2-9E5A-412C-8C77-AB100E24C1DF}
-; same as above
-
-[RC webm]
-glob=*.webm
-params=copy
-productAssetType={DDFEE0B2-9E5A-412C-8C77-AB100E24C1DF}
-; same as above
-
-[RC mov]
-glob=*.mov
-params=copy
-productAssetType={DDFEE0B2-9E5A-412C-8C77-AB100E24C1DF}
-; same as above
-
-[RC bk2]
-glob=*.bk2
-params=copy
-productAssetType={BF4879B9-B893-41D2-80E9-24A7BDCD2B50}
-
-[RC img]
-glob=*.img
-params=copy
-
-[RC dba]
-glob=*.dba
-params=copy
-productAssetType={511562BE-65A5-4538-A5F1-AC685366243E}
-version=2
-
-[RC cgf]
-glob=*.cgf
-params=/VertexPositionFormat=exporter /VertexIndexFormat=u32
-; on server, feed rc.exe the param /p=pc to force it to compile assets for server platform in pc format.
-server=/VertexPositionFormat=exporter /VertexIndexFormat=u32 /p=pc
-lockSource=true
-priority=10
-; allow CGF files to compile first, so untextured models appear before their textures for faster startup
-; other available params: /SplitLODs=1
-
-[RC surfaceTagNameList]
-glob=*.surfaceTagNameList
-params=copy
-productAssetType={A471B2A9-85FC-4993-842D-1881CBC03A2B}
-
-[RC gradImageSettings]
-glob=*.gradimagesettings
-params=copy
-productAssetType={B36FEB5C-41B6-4B58-A212-21EF5AEF523C}
-
-[RC fbx]
-glob=*.fbx
-; Priority set to 9 so its "before" things like materials but after things like actors and motions (which build using a proper AssetBuilderSDK builder and thus are not in this file)
-priority=9
-version=5
-
-[RC chr]
-glob=*.chr
-params=copy
-productAssetType={60161B46-21F0-4396-A4F0-F2CCF0664CDE}
-version=2
-
-[RC skin]
-glob=*.skin
-params=copy
-
-[RC cfi]
-glob=*.cfi
-params=copy
-
-[RC cfx]
-glob=*.cfx
-params=copy
-
-[RC cfr]
-glob=*.cfr
-params=copy
-
-; Warning: If you change the VertexIndexFormat, make sure you update the vtx_idx typedef in Code\CryEngine\CryCommon\ProjectDefines.h
-[RC abc]
-glob=*.abc
-params=/SkipFilesWithoutBuildConfig=0 /VertexIndexFormat=u32
-console=/SkipFilesWithoutBuildConfig=0 /VertexIndexFormat=u32
-mobile=/SkipFilesWithoutBuildConfig=0 /VertexIndexFormat=u16
-version=3
-server=skip
-
-[RC png-entityicon]
-pattern=(.*EntityIcons\\/).*\\.png
-productAssetType={3436C30E-E2C5-4C3B-A7B9-66C94A28701B}
-params=skip ; only tools-supporting platforms should copy this file.  Everyone else can skip.
-tools=copy
-
-[RC usm]
-glob=*.usm
-params=copy
-server=skip
-
-[RC animevents]
-glob=*.animevents
-params=copy
-productAssetType={C1D209C1-F81A-4586-A34E-1615995F9F3F}
-version=2
-
-[RC adb]
-glob=*.adb
-params=copy
-productAssetType={50908273-CA36-4668-9828-15DD5092F973}
-
-[RC bspace]
-glob=*.bspace
-params=copy
-
-[RC cdf]
-glob=*.cdf
-params=copy
-productAssetType={DF036C63-9AE6-4AC3-A6AC-8A1D76126C01}
-; note - this used to be skinnedMeshAsset but its now Character Definition File specific.
-; .skin has its own type.
-
-[RC chrparams]
-glob=*.chrparams
-params=copy
-productAssetType={4BBB785A-6824-4803-A607-F9323E7BEEF1}
-version=2
-
-[RC comb]
-glob=*.comb
-params=copy
-
-[RC dlg]
-glob=*.dlg
-params=copy
-
-[RC csv]
-glob=*.csv
-params=copy
-
-[RC json]
-glob=*.json
-params=copy
-
-[RC lmg]
-glob=*.lmg
-params=copy
-
-[RC smtl]
-glob=*.smtl
-params=copy
-
-[RC sub]
-glob=*.sub
-params=copy
-productAssetType={71F9D30E-13F7-40D6-A3C9-E5358004B31F}
-version=2
-
-[RC sbsar]
-glob=*.sbsar
-params=copy
-
-[RC loc.agsxml]
-glob=*.loc.agsxml
-params=copy
-version=1
-
-[RC node]
-glob=*.node
-params=copy
-
-[RC veg]
-glob=*.veg
-params=copy
-
-[RC dat]
-glob=*.dat
-params=copy
-
-[RC lut]
-glob=*.lut
-params=copy
-
-[RC txt]
-pattern=^(?!.*PreloadLibs.txt).*\\.txt
-params=copy
-
-[RC cal]
-glob=*.cal
-params=copy
-
-[RC grp]
-glob=*.grp
-params=copy
-productAssetType={7629EDD3-A361-49A2-B271-252127097D81}
-version=2
-
-[RC xls]
-glob=*.xls
-params=copy
-
-[RC ini]
-glob=*.ini
-params=copy
-
-[RC ttf]
-glob=*.ttf
-params=copy
-
-[RC otf]
-glob=*.otf
-params=copy
-
-[RC ext]
-glob=*.ext
-params=copy
-
-[RC pak]
-; Copy all pak files except level.pak, level.pak has its own builder.
-pattern=^((?!\\/level\\.pak).)*\\.pak$
-params=copy
-
-[RC ctc]
-glob=*.ctc
-params=copy
-
-[RC uiprefab]
-glob=*.uiprefab
-params=copy
-server=skip
-
-[RC sprite]
-glob=*.sprite
-params=copy
-server=skip
-
-[RC bin]
-glob=*.bin
-params=copy
-
-[RC inputbindings]
-glob=*.inputbindings
-params=copy
-productAssetType={25971C7A-26E2-4D08-A146-2EFCC1C36B0C}
-
-[RC physmaterial]
-glob=*.physmaterial
-params=copy
-productAssetType={9E366D8C-33BB-4825-9A1F-FA3ADBE11D0F}
-
-[RC ocm]
-glob=*.ocm
-params=copy
-
-; Feature tests use the raw .tif files for the golden image comparison
-[RC goldenimages]
-pattern=.*GoldenImages\\/.*\\.tif
-params=copy 
-server=skip
-
-; Copy over certificates for use with FileDataSource
-[RC CertificatePEM]
-glob=*.pem
-params=copy
-
-; Copy over certificates for use with Dynamic Content
-[RC CertificateDER]
-glob=*.der
-params=copy
-
-[RC PhysXMeshAsset]
-glob=*.pxmesh
-params=copy
-productAssetType={7A2871B9-5EAB-4DE0-A901-B0D2C6920DDB}
-
-; Copy over cooked PhysX heightfield
-[RC PhysX HeightField]
-glob=*.pxheightfield
-params=copy
-productAssetType={B61189FE-B2D7-4AF1-8951-CB5C0F7834FC}
-
-[RC filetag]
-glob=*.filetag
-params=copy
-productAssetType={F3BE5CAB-85B7-44B7-9495-863863F6B267}
-
-; Precompiled shader srg
-[RC azsrg]
-glob=*.azsrg
-params=copy
-productAssetType={F8C9F4AE-3F6A-45AD-B4FB-0CA415FCC2E1}
-
-; Precompiled shader variant
-[RC azshadervariant]
-glob=*.azshadervariant
-params=copy
-productAssetType={9F4D654B-4439-4C61-8DCD-F1C7C5560768}

+ 224 - 15
Engine/Registry/AssetProcessorPlatformConfig.setreg → AssetProcessorPlatformConfig.setreg

@@ -1,4 +1,23 @@
 {
 {
+    // ---- Enable/Disable platforms for the entire project. AssetProcessor will automatically add the current platform by default. 
+
+    // PLATFORM DEFINITIONS
+    // [Platform (unique identifier)]
+    // tags=(comma-seperated-tags)
+    //
+    // note:  the 'identifier' of a platform is the word(s) following the "Platform" keyword (so [Platform pc] means identifier
+    //        is 'pc' for example.  This is used to name its assets folder in the cache and should be used in your bootstrap.cfg
+    //        or your main.cpp to choose what assets to load for that particular platform.
+    //        Its primary use is to enable additional non-host platforms (Ios, android...) that are not the current platform.
+    // note:  'tags' is a comma-seperated list of tags to tag the platform with that builders can inspect to decide what to do.
+
+    // while builders can accept any tags you add in order to make decisions, common tags are
+    // tools - this platform can host the tools and editor and such
+    // renderer - this platform runs the client engine and renders on a GPU.  If missing we could be on a server-only platform
+    // mobile - a mobile platform such as a set top box or phone with limited resources
+    // console - a console platform
+    // server - a server platform of some kind, usually headless, no renderer.
+
     "Amazon": {
     "Amazon": {
         "AssetProcessor": {
         "AssetProcessor": {
             "Settings": {
             "Settings": {
@@ -14,27 +33,82 @@
                 "Platform osx_gl": {
                 "Platform osx_gl": {
                     "tags": "tools,renderer,metal"
                     "tags": "tools,renderer,metal"
                 },
                 },
+                // this is an example of a headless platform that has no renderer.   
+                // To use this you would still need to make sure 'assetplatform' in your startup params in your main() chooses this 'server' platform as your server 'assets' flavor
                 "Platform server": {
                 "Platform server": {
                     "tags": "server,dx12,vulkan"
                     "tags": "server,dx12,vulkan"
                 },
                 },
+                // this section allows you to turn on various platforms in addition to the host platform you're running on
+                // 'enabled' is AUTOMATICALLY TRUE for the current platform that you are running on, so it is not necessary to force it to true for that platform
+                // To enable any additional platform, just uncomment the appropriate line below.
+                "Platforms": {
+                    //"pc": "enabled",
+                    //"es3": "enabled",
+                    //"ios": "enabled",
+                    //"osx_gl": "enabled",
+                    //"server": "enabled"
+                },
+                // ---- The number of worker jobs, 0 means use the number of Logical Cores
                 "Jobs": {
                 "Jobs": {
                     "minJobs": 1,
                     "minJobs": 1,
                     "maxJobs": 0
                     "maxJobs": 0
                 },
                 },
+                // cacheServerAddress is the location of the asset server cache.
+                // Currently for a network share server this would be the absolute file path to the network share folder.
+                "Server": {
+                    //"cacheServerAddress": ""
+                },
+
+                // ---- add any metadata file type here that needs to be monitored by the AssetProcessor.
+                // Modifying these meta file will cause the source asset to re-compile again.
+                // They are specified in the following format
+                // metadata extension=original extension to replace
+                // if the metadata extension does not replace the original, then the original can be blank
+                // so for example if your normal file is blah.tif and your metafile for that file is blah.tif.exportsettings
+                // then your declaration would be exportsettings=   ; ie, it would be blank
+                // however if your metafile REPLACES the extension (for example, if you have the file blah.i_caf and its metafile is blah.exportsettings)
+                // then you specify the original extension here to narrow the scope.
+                // If a relative path to a specific file is provided instead of an extension, a change to the file will change all files
+                // with the associated extension (e.g. Animations/SkeletonList.xml=i_caf will cause all i_caf files to recompile when 
+                // Animations/SkeletonList.xml within the current game project changes)
+
                 "MetaDataTypes": {
                 "MetaDataTypes": {
                     "animsettings": "i_caf",
                     "animsettings": "i_caf",
-                    "Animations": {
-                        "SkeletonList.xml": "i_caf"
-                    },
+                    "Animations/SkeletonList.xml": "i_caf",
                     "cbc": "abc",
                     "cbc": "abc",
                     "fbx.assetinfo": "fbx"
                     "fbx.assetinfo": "fbx"
                 },
                 },
+
+                // ---- add any folders to scan here.  The priority order is the order they appear here
+                // available macros are 
+                // @ROOT@ - the location of asset root
+                // @PROJECTROOT@ - the location of the project root, for example 'Q:\MyProjects\RPGSample' 
+                // note that they are sorted by their 'order' value, and the lower the order the more important an asset is
+                // lower order numbers override higher ones.
+                // If specified, output will be prepended to every path found in that recognizer's watch folder.
+                // Note that you can also make the scan folder platform specific by using the keywords include and exclude.
+                // Both include and exclude can contain either platform tags, platform identifiers or both.
+                // if no include is specified, all currently enabled platforms are included by default.
+                // If includes ARE specified, it will be filtered down by the list of currently enabled platforms. 
+                // "ScanFolder (unique identifier)": {
+                //  "include": "(comma seperated platform tags or identifiers)",
+                //  "exclude": "(comma seperated platform tags or identifiers)"
+                // }
+                // For example if you want to include a scan folder only for platforms that have the platform tags tools and renderer 
+                // but omit it for platform osx_gl, you will have a scanfolder rule like
+                // "ScanFolder (unique identifier)": {
+                // "watch": "@ROOT@/foo",
+                // "include": "tools, renderer",
+                // "exclude": "osx_gl"
+                // }
+
                 "ScanFolder Game": {
                 "ScanFolder Game": {
-                    "watch": "@ROOT@/@GAMENAME@",
-                    "display": "@GAMENAME@",
+                    "watch": "@PROJECTROOT@",
+                    "display": "@PROJECTROOT@",
                     "recursive": 1,
                     "recursive": 1,
                     "order": 0
                     "order": 0
                 },
                 },
+                // gems will be auto-added from 100 onwards
                 "ScanFolder Root": {
                 "ScanFolder Root": {
                     "watch": "@ROOT@",
                     "watch": "@ROOT@",
                     "recursive": 0,
                     "recursive": 0,
@@ -52,6 +126,9 @@
                     "order": 30000,
                     "order": 30000,
                     "include": "tools,renderer"
                     "include": "tools,renderer"
                 },
                 },
+
+                // Excludes files that match the pattern or glob 
+                // if you use a pattern, remember to escape your backslashes (\\)
                 "Exclude _LevelBackups": {
                 "Exclude _LevelBackups": {
                     "pattern": ".*\\\\/Levels\\\\/.*\\\\/_savebackup\\\\/.*"
                     "pattern": ".*\\\\/Levels\\\\/.*\\\\/_savebackup\\\\/.*"
                 },
                 },
@@ -61,6 +138,7 @@
                 "Exclude HoldFiles": {
                 "Exclude HoldFiles": {
                     "pattern": ".*\\\\/Levels\\\\/.*_hold\\\\/.*"
                     "pattern": ".*\\\\/Levels\\\\/.*_hold\\\\/.*"
                 },
                 },
+                // note that $ has meaning to regex, so we escape it.
                 "Exclude TempFiles": {
                 "Exclude TempFiles": {
                     "pattern": ".*\\\\/\\\\$tmp[0-9]*_.*"
                     "pattern": ".*\\\\/\\\\$tmp[0-9]*_.*"
                 },
                 },
@@ -88,6 +166,16 @@
                 "Exclude CMakeFiles": {
                 "Exclude CMakeFiles": {
                     "pattern": ".*\\\\/.*\\\\.cmake"
                     "pattern": ".*\\\\/.*\\\\.cmake"
                 },
                 },
+                "Exclude User": {
+                    "pattern": ".*/[Uu]ser/.*"
+                },
+                "Exclude Build": {
+                    "pattern": ".*/[Bb]uild/.*"
+                },
+
+                // ------------------------------------------------------------------------------
+                // Large Worlds Test
+                // ------------------------------------------------------------------------------
                 "Exclude Work In Progress Folders": {
                 "Exclude Work In Progress Folders": {
                     "pattern": ".*\\\\/WIP\\\\/.*"
                     "pattern": ".*\\\\/WIP\\\\/.*"
                 },
                 },
@@ -97,9 +185,112 @@
                 "Exclude Art Source Folders": {
                 "Exclude Art Source Folders": {
                     "pattern": ".*\\\\/ArtSource\\\\/.*"
                     "pattern": ".*\\\\/ArtSource\\\\/.*"
                 },
                 },
+                //------------------------------------------------------------------------------
+                // RC params mapping examples
+                //------------------------------------------------------------------------------
+
+                // note that productAssetType is a means of setting the output asset Type (as in AZ::Data::AssetType) of a simple job
+                // and is the recommended way to specify that a certain kind of file (such as '*.myextension') becomes registered as the
+                // actual UUID of that type in the engine itself.
+
+                // Use a regex for matching files, same params for all platforms
+                // "RC TGAs": {
+                //  "pattern": ".+\\\\.tga$",
+                //  "params": "/tga /texture"
+                //}
+
+                // Use a glob, have special params for es3 platform
+                // "RC TIFFs": {
+                //  "glob": "*.tif",
+                //  "params": "/texture",
+                //  "es3": "/pvrt"
+                //}
+
+                // You can also modify a version to compile all matching files again
+                // By default the version is empty
+                // "RC tif": {
+                //  "glob": "*.tif",
+                //  "params": "\\someparams",
+                //  "version": 1.0
+                //}
+                // This will make the AssetProcessor compile all the .tif files again
+
+                // you can also optionally supply a priority.
+                // this is used to sort jobs when no other external circumstance sorts them
+                // for example, copy jobs will be higher in priority than other jobs that are not copy jobs
+                // however if they're both copy jobs or both not, and no other circumstances apply, then priority will be used.
+                // default priority is zero if not specified
+
+                // you can specify an option to skip processing for a file type based on the platform.
+                // for example, if you dont want to process tif files for ios, you can make tif files
+                // process on any platform except for ios:
+                // "RC tif": {
+                //  "glob": "*.tif",
+                //  "params": "\\someparams",
+                //  "ios": "skip"
+                //}
+
+                // you can specify an option to output product dependencies for a copy job.
+                // please note that you only need to set this option when cry code is required to parse the asset.
+                // otherwise product dependencies will be output automatically by the CopyDependencyBuilder.
+                // for example, if you want to output the product dependencies for font assets:
+                // "RC font": {
+                //  "glob": "*.font",
+                //  "params": "copy",
+                //  "outputProductDependencies": true
+                //}
+
+                // you can also specify an option to make all jobs critical that matches some pattern/glob.
+                // for example, if you want to make all png files critical than set critical to true.
+                // Note that by default all copy jobs are critical.
+                // Critical jobs are processed before non critical jobs and also prevent the runtime or editor from starting until they are all complete.
+                // "RC png": {
+                //  "glob": "*.png",
+                //  "params": "\\someparams",
+                //  "critical": true
+                //}
+
+                // you can also specify an option to make all the job store in the asset server cache location if you are running AP in server mode. 
+                // For example, if you want to store all png jobs in the asset server cache location including their logs, you can set checkServer = true.
+                // The client(i.e if you are running AP in non-server mode) will also check for this flag to know which jobs to fetch from the asset server cache location.
+                // if unsucessful, it will process the job locally as usual.
+                // "RC png": {
+                //  "glob": "*.png",
+                //  "params": "\\someparams",
+                //  "critical": true,
+                //  "checkServer": true
+                //}
+
+                // note that the FULL PATH to the file will be used as the match, not the relative path
+                // so ensure start your patterns with .* or as appropriate.
+                // Also, any rules which match will apply - so if you have two rules which both apply to PNG files for example
+                // but you only want one, you might want to use exclusion patterns:
+                 
+                //Example: process everything EXCEPT the ones in the libs/ui folder with these params
+                // "RC png-normal": {
+                //  "pattern": "(?!.*libs\\\\/ui\\\\/).*\\.png",
+                //  "params": "/imagecompressor=CTSquish /streaming=0",
+                //  "lockSource": true
+                //}
+
+                //Example:  Process everything in the libs/ui folder with linear color space
+                // "RC png-ui": {
+                //  "pattern": "(.*libs\\\\/ui\\\\/).*\\.png",
+                //  "params": "/imagecompressor=CTSquish /streaming=0 /colorspace=linear,linear",
+                //  "lockSource": true
+                //}
+
+                // More example Regexes:
+                // "pattern": "(?!(.*libs\\\\/ui\\\\/)|(.*editor\\\\/).*\\\\.png"
+                // This pattern will not match anything with editor/ or libs/ui/ in it
+                // "pattern": "((.*libs\\\\/ui\\\\/)|(.*editor\\\\/).*\\\\.png"
+                // This pattern will only match anything with editor/ or libs/ui/ in it
+
+                // Give every [Section Name] its own unique Name or else they will overwrite each other!
                 "RC i_caf": {
                 "RC i_caf": {
                     "glob": "*.i_caf",
                     "glob": "*.i_caf",
                     "params": "/cafAlignTracks=1 /animConfigFolder=Animations /skipdba=1 /refresh=1",
                     "params": "/cafAlignTracks=1 /animConfigFolder=Animations /skipdba=1 /refresh=1",
+                    // force server to send the 'pc' platform to RC.EXE so it compiles the same as PC.
                     "server": "/cafAlignTracks=1 /animConfigFolder=Animations /skipdba=1 /refresh=1 /p=pc",
                     "server": "/cafAlignTracks=1 /animConfigFolder=Animations /skipdba=1 /refresh=1 /p=pc",
                     "priority": 5,
                     "priority": 5,
                     "productAssetType": "{6023CFF8-FCBA-4528-A8BF-6E0E10B9AB9C}"
                     "productAssetType": "{6023CFF8-FCBA-4528-A8BF-6E0E10B9AB9C}"
@@ -147,9 +338,12 @@
                 "RC cgf": {
                 "RC cgf": {
                     "glob": "*.cgf",
                     "glob": "*.cgf",
                     "params": "/VertexPositionFormat=exporter /VertexIndexFormat=u32",
                     "params": "/VertexPositionFormat=exporter /VertexIndexFormat=u32",
+                    // on server, feed rc.exe the param /p=pc to force it to compile assets for server platform in pc format.
                     "server": "/VertexPositionFormat=exporter /VertexIndexFormat=u32 /p=pc",
                     "server": "/VertexPositionFormat=exporter /VertexIndexFormat=u32 /p=pc",
                     "lockSource": true,
                     "lockSource": true,
                     "priority": 10
                     "priority": 10
+                    // allow CGF files to compile first, so untextured models appear before their textures for faster startup
+                    // other available params: /SplitLODs=1
                 },
                 },
                 "RC surfaceTagNameList": {
                 "RC surfaceTagNameList": {
                     "glob": "*.surfaceTagNameList",
                     "glob": "*.surfaceTagNameList",
@@ -163,8 +357,9 @@
                 },
                 },
                 "RC fbx": {
                 "RC fbx": {
                     "glob": "*.fbx",
                     "glob": "*.fbx",
+                    // Priority set to 9 so its "before" things like materials but after things like actors and motions (which build using a proper AssetBuilderSDK builder and thus are not in this file)
                     "priority": 9,
                     "priority": 9,
-                    "version": 4
+                    "version": 5
                 },
                 },
                 "RC chr": {
                 "RC chr": {
                     "glob": "*.chr",
                     "glob": "*.chr",
@@ -188,6 +383,7 @@
                     "glob": "*.cfr",
                     "glob": "*.cfr",
                     "params": "copy"
                     "params": "copy"
                 },
                 },
+                // Warning: If you change the VertexIndexFormat, make sure you update the vtx_idx typedef in Code\CryEngine\CryCommon\ProjectDefines.h
                 "RC abc": {
                 "RC abc": {
                     "glob": "*.abc",
                     "glob": "*.abc",
                     "params": "/SkipFilesWithoutBuildConfig=0 /VertexIndexFormat=u32",
                     "params": "/SkipFilesWithoutBuildConfig=0 /VertexIndexFormat=u32",
@@ -199,7 +395,7 @@
                 "RC png-entityicon": {
                 "RC png-entityicon": {
                     "pattern": "(.*EntityIcons\\\\/).*\\\\.png",
                     "pattern": "(.*EntityIcons\\\\/).*\\\\.png",
                     "productAssetType": "{3436C30E-E2C5-4C3B-A7B9-66C94A28701B}",
                     "productAssetType": "{3436C30E-E2C5-4C3B-A7B9-66C94A28701B}",
-                    "params": "skip ; only tools-supporting platforms should copy this file.  Everyone else can skip.",
+                    "params": "skip",
                     "tools": "copy"
                     "tools": "copy"
                 },
                 },
                 "RC usm": {
                 "RC usm": {
@@ -227,6 +423,9 @@
                     "params": "copy",
                     "params": "copy",
                     "productAssetType": "{DF036C63-9AE6-4AC3-A6AC-8A1D76126C01}"
                     "productAssetType": "{DF036C63-9AE6-4AC3-A6AC-8A1D76126C01}"
                 },
                 },
+                // note - this used to be skinnedMeshAsset but its now Character Definition File specific.
+                // .skin has its own type.
+
                 "RC chrparams": {
                 "RC chrparams": {
                     "glob": "*.chrparams",
                     "glob": "*.chrparams",
                     "params": "copy",
                     "params": "copy",
@@ -272,13 +471,6 @@
                     "params": "copy",
                     "params": "copy",
                     "version": 1
                     "version": 1
                 },
                 },
-                "RC Editor Slice Copy": {
-                    "glob": "*.slice",
-                    "params": "copy",
-                    "critical": true,
-                    "productAssetType": "{C62C7A87-9C09-4148-A985-12F2C99C0A45}",
-                    "priority": 2
-                },
                 "RC node": {
                 "RC node": {
                     "glob": "*.node",
                     "glob": "*.node",
                     "params": "copy"
                     "params": "copy"
@@ -329,6 +521,7 @@
                     "glob": "*.ext",
                     "glob": "*.ext",
                     "params": "copy"
                     "params": "copy"
                 },
                 },
+                // Copy all pak files except level.pak, level.pak has its own builder.
                 "RC pak": {
                 "RC pak": {
                     "pattern": "^((?!\\\\/level\\\\.pak).)*\\\\.pak$",
                     "pattern": "^((?!\\\\/level\\\\.pak).)*\\\\.pak$",
                     "params": "copy"
                     "params": "copy"
@@ -365,15 +558,18 @@
                     "glob": "*.ocm",
                     "glob": "*.ocm",
                     "params": "copy"
                     "params": "copy"
                 },
                 },
+                // Feature tests use the raw .tif files for the golden image comparison
                 "RC goldenimages": {
                 "RC goldenimages": {
                     "pattern": ".*GoldenImages\\\\/.*\\\\.tif",
                     "pattern": ".*GoldenImages\\\\/.*\\\\.tif",
                     "params": "copy",
                     "params": "copy",
                     "server": "skip"
                     "server": "skip"
                 },
                 },
+                // Copy over certificates for use with FileDataSource
                 "RC CertificatePEM": {
                 "RC CertificatePEM": {
                     "glob": "*.pem",
                     "glob": "*.pem",
                     "params": "copy"
                     "params": "copy"
                 },
                 },
+                // Copy over certificates for use with Dynamic Content
                 "RC CertificateDER": {
                 "RC CertificateDER": {
                     "glob": "*.der",
                     "glob": "*.der",
                     "params": "copy"
                     "params": "copy"
@@ -383,6 +579,7 @@
                     "params": "copy",
                     "params": "copy",
                     "productAssetType": "{7A2871B9-5EAB-4DE0-A901-B0D2C6920DDB}"
                     "productAssetType": "{7A2871B9-5EAB-4DE0-A901-B0D2C6920DDB}"
                 },
                 },
+                // Copy over cooked PhysX heightfield
                 "RC PhysX HeightField": {
                 "RC PhysX HeightField": {
                     "glob": "*.pxheightfield",
                     "glob": "*.pxheightfield",
                     "params": "copy",
                     "params": "copy",
@@ -392,8 +589,20 @@
                     "glob": "*.filetag",
                     "glob": "*.filetag",
                     "params": "copy",
                     "params": "copy",
                     "productAssetType": "{F3BE5CAB-85B7-44B7-9495-863863F6B267}"
                     "productAssetType": "{F3BE5CAB-85B7-44B7-9495-863863F6B267}"
+                },
+                // Precompiled shader srg
+                "RC azsrg": {
+                    "glob": "*.azsrg",
+                    "params": "copy",
+                    "productAssetType": "{F8C9F4AE-3F6A-45AD-B4FB-0CA415FCC2E1}"
+                },
+                // Precompiled shader variant
+                "RC azshadervariant": {
+                    "glob": "*.azshadervariant",
+                    "params": "copy",
+                    "productAssetType": "{9F4D654B-4439-4C61-8DCD-F1C7C5560768}"
                 }
                 }
             }
             }
         }
         }
     }
     }
-}
+}

+ 66 - 45
AutomatedReview/Jenkinsfile

@@ -119,6 +119,7 @@ def LoadPipelineConfig(String pipelineName, String branchName) {
     PullFilesFromGit(PIPELINE_CONFIG_FILE, branchName)
     PullFilesFromGit(PIPELINE_CONFIG_FILE, branchName)
     def pipelineConfig = {}
     def pipelineConfig = {}
     pipelineConfig = readJSON file: PIPELINE_CONFIG_FILE
     pipelineConfig = readJSON file: PIPELINE_CONFIG_FILE
+    palRm(PIPELINE_CONFIG_FILE)
     pipelineConfig.platforms = EMPTY_JSON
     pipelineConfig.platforms = EMPTY_JSON
 
 
     // Load the pipeline configs per platform
     // Load the pipeline configs per platform
@@ -137,6 +138,7 @@ def LoadPipelineConfig(String pipelineName, String branchName) {
                 pipelineConfig.platforms[platform] = EMPTY_JSON
                 pipelineConfig.platforms[platform] = EMPTY_JSON
                 pipelineConfig.platforms[platform].PIPELINE_ENV = readJSON file: pipeline_config_path.toString()
                 pipelineConfig.platforms[platform].PIPELINE_ENV = readJSON file: pipeline_config_path.toString()
             }
             }
+            palRm(pipeline_config_path.toString())
         }
         }
     }
     }
 
 
@@ -155,6 +157,7 @@ def LoadPipelineConfig(String pipelineName, String branchName) {
             if(platform) {
             if(platform) {
                 pipelineConfig.platforms[platform].build_types = readJSON file: build_config_path.toString()
                 pipelineConfig.platforms[platform].build_types = readJSON file: build_config_path.toString()
             }
             }
+            palRm(build_config_path.toString())
         }
         }
     }
     }
     return pipelineConfig
     return pipelineConfig
@@ -202,39 +205,45 @@ def PullFilesFromGit(String filenamePath, String branchName, boolean failIfNotFo
     folderPathParts.remove(folderPathParts.size()-1) // remove the filename
     folderPathParts.remove(folderPathParts.size()-1) // remove the filename
     def folderPath = folderPathParts.join('/')
     def folderPath = folderPathParts.join('/')
     if (folderPath.contains('*')) {
     if (folderPath.contains('*')) {
-        
-        def currentPath = ''
-        for (int i = 0; i < folderPathParts.size(); i++) {
-            if (folderPathParts[i] == '*') {
-                palMkdir(currentPath)
-                retry(3) { palSh("aws codecommit get-folder --repository-name ${repositoryName} --commit-specifier ${branchName} --folder-path ${currentPath} > ${currentPath}/.codecommit", "GetFolder ${currentPath}") }
-                def folderInfo = readJSON file: "${currentPath}/.codecommit"
-                folderInfo.subFolders.each { folder ->
-                    def newSubPath = currentPath + '/' + folder.relativePath
-                    for (int j = i+1; j < folderPathParts.size(); j++) {
-                        newSubPath = newSubPath + '/' + folderPathParts[j]
+
+        try {
+            def currentPath = ''
+            for (int i = 0; i < folderPathParts.size(); i++) {
+                if (folderPathParts[i] == '*') {
+                    palMkdir(currentPath)
+                    retry(3) { palSh("aws codecommit get-folder --repository-name ${repositoryName} --commit-specifier ${branchName} --folder-path ${currentPath} > ${currentPath}/.codecommit", "GetFolder ${currentPath}") }
+                    def folderInfo = readJSON file: "${currentPath}/.codecommit"
+                    folderInfo.subFolders.each { folder ->
+                        def newSubPath = currentPath + '/' + folder.relativePath
+                        for (int j = i+1; j < folderPathParts.size(); j++) {
+                            newSubPath = newSubPath + '/' + folderPathParts[j]
+                        }
+                        newSubPath = newSubPath + '/' + filename
+                        PullFilesFromGit(newSubPath, branchName, false, repositoryName)
                     }
                     }
-                    newSubPath = newSubPath + '/' + filename
-                    PullFilesFromGit(newSubPath, branchName, false, repositoryName)
+                    palRm("${currentPath}/.codecommit")
+                }
+                if (i == 0) {
+                    currentPath = folderPathParts[i]
+                } else {
+                    currentPath = currentPath + '/' + folderPathParts[i]
                 }
                 }
-                palRm("${currentPath}/.codecommit")
-            }
-            if (i == 0) {
-                currentPath = folderPathParts[i]
-            } else {
-                currentPath = currentPath + '/' + folderPathParts[i]
             }
             }
+        } catch(Exception e) {
         }
         }
 
 
     } else if (filename.contains('*')) {
     } else if (filename.contains('*')) {
 
 
-        palMkdir(folderPath)
-        retry(3) { palSh("aws codecommit get-folder --repository-name ${repositoryName} --commit-specifier ${branchName} --folder-path ${folderPath} > ${folderPath}/.codecommit", "GetFolder ${folderPath}") }
-        def folderInfo = readJSON file: "${folderPath}/.codecommit"
-        folderInfo.files.each { file ->
-            PullFilesFromGit("${folderPath}/${filename}", branchName, false, repositoryName)
+        try {
+            palMkdir(folderPath)
+            retry(3) { palSh("aws codecommit get-folder --repository-name ${repositoryName} --commit-specifier ${branchName} --folder-path ${folderPath} > ${folderPath}/.codecommit", "GetFolder ${folderPath}") }
+            def folderInfo = readJSON file: "${folderPath}/.codecommit"
+            folderInfo.files.each { file ->
+                PullFilesFromGit("${folderPath}/${filename}", branchName, false, repositoryName)
+            }
+            palRm("${folderPath}/.codecommit")
+        } catch(Exception e) {
         }
         }
-        palRm("${folderPath}/.codecommit")
 
 
     } else {
     } else {
 
 
@@ -271,18 +280,7 @@ def PullFilesFromGit(String filenamePath, String branchName, boolean failIfNotFo
     }
     }
 }
 }
 
 
-def SetLfsCredentials(cmd, lbl = '') {
-    if (env.IS_UNIX) {
-        sh label: lbl,
-           script: cmd
-    } else { 
-        bat label: lbl,
-            script: cmd
-    }
-}
-
 def CheckoutRepo(boolean disableSubmodules = false) {
 def CheckoutRepo(boolean disableSubmodules = false) {
-    palSh('git lfs uninstall', 'Git LFS Uninstall')  // Prevent git from pulling lfs objects during checkout
 
 
     if(fileExists('.git')) {
     if(fileExists('.git')) {
         // If the repository after checkout is locked, likely we took a snapshot while git was running,
         // If the repository after checkout is locked, likely we took a snapshot while git was running,
@@ -292,7 +290,7 @@ def CheckoutRepo(boolean disableSubmodules = false) {
             palSh('git gc', 'Git GarbageCollect')
             palSh('git gc', 'Git GarbageCollect')
         }
         }
         if(fileExists(indexLockFile)) { // if it is still there, remove it
         if(fileExists(indexLockFile)) { // if it is still there, remove it
-            palRm(indexLockFile, 'Remove index.lock')
+            palRm(indexLockFile)
         }
         }
         palSh('git remote prune origin', 'Git reset')
         palSh('git remote prune origin', 'Git reset')
     }
     }
@@ -329,14 +327,6 @@ def CheckoutRepo(boolean disableSubmodules = false) {
         }
         }
     }
     }
 
 
-    // Run lfs in a separate step. Jenkins is unable to load the credentials for the custom LFS endpoint
-    withCredentials([usernamePassword(credentialsId: "${env.GITHUB_USER}", passwordVariable: 'accesstoken', usernameVariable: 'username')]) {
-        SetLfsCredentials("git config -f .lfsconfig lfs.url https://${username}:${accesstoken}@${env.LFS_URL}", 'Set credentials')
-    }
-    palSh('git lfs install', 'Git LFS Install')
-    palSh('git lfs pull', 'Git LFS Pull')
-}
-
     // CHANGE_ID is used by some scripts to identify uniquely the current change (usually metric jobs)
     // CHANGE_ID is used by some scripts to identify uniquely the current change (usually metric jobs)
     palSh('git rev-parse HEAD > commitid', 'Getting commit id')
     palSh('git rev-parse HEAD > commitid', 'Getting commit id')
     env.CHANGE_ID = readFile file: 'commitid'
     env.CHANGE_ID = readFile file: 'commitid'
@@ -406,6 +396,26 @@ def Build(Map options, String platform, String type, String workspace) {
     }
     }
 }
 }
 
 
+def TestMetrics(Map options, Map buildType, String workspace, String branchName, String repoName) {
+    catchError(buildResult: null, stageResult: null) {
+        def cmakeBuildDir = [workspace, buildType.value.PARAMETERS.OUTPUT_DIRECTORY].join('/')
+        def command = "${options.PYTHON_DIR}/python.cmd -u mars/scripts/python/ctest_test_metric_scraper.py -e jenkins.creds.user ${username} -e jenkins.creds.pass ${apitoken} ${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${buildType.value.PARAMETERS.CONFIGURATION} ${repoName} "
+        if (params.DESTINATION_BRANCH)
+            command += '--destination-branch "$DESTINATION_BRANCH" '
+        dir(workspace) {
+            checkout scm: [
+                $class: 'GitSCM',
+                extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'mars']],
+                userRemoteConfigs: [[url: "${env.MARS_REPO}", name: 'mars']]
+            ]
+            withCredentials([usernamePassword(credentialsId: "${env.SERVICE_USER}", passwordVariable: 'apitoken', usernameVariable: 'username')]) {
+                bat label: "Publishing ${buildType.key} Test Metrics",
+                script: command
+            }
+        }
+    }
+}
+
 def PostBuildCommonSteps(String workspace, boolean mount = true) {
 def PostBuildCommonSteps(String workspace, boolean mount = true) {
     echo 'Starting post-build common steps...'
     echo 'Starting post-build common steps...'
 
 
@@ -448,6 +458,14 @@ def CreateBuildStage(Map pipelineConfig, String platformName, String jobName, Ma
     }
     }
 }
 }
 
 
+def CreateTestMetricsStage(Map pipelineConfig, Map buildJob, String branchName, Map environmentVars) {
+    return {
+        stage("${buildJob.key}") {
+            TestMetrics(pipelineConfig, buildJob, environmentVars['WORKSPACE'], branchName, env.DEFAULT_REPOSITORY_NAME)
+        }
+    }
+}
+
 def CreateTeardownStage(Map environmentVars) {
 def CreateTeardownStage(Map environmentVars) {
     return {
     return {
         stage("Teardown") {
         stage("Teardown") {
@@ -538,6 +556,9 @@ try {
                                     } else {
                                     } else {
                                         CreateBuildStage(pipelineConfig,  platform.key, build_job.key, envVars).call()
                                         CreateBuildStage(pipelineConfig,  platform.key, build_job.key, envVars).call()
                                     }
                                     }
+                                    if (env.MARS_REPO && platform.key == 'Windows' && build_job.key.startsWith('test')) {
+                                        CreateTestMetricsStage(pipelineConfig, build_job, branchName, envVars).call()
+                                    }
                                 }   
                                 }   
                                 catch(Exception e) {
                                 catch(Exception e) {
                                     //  https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/Result.java
                                     //  https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/Result.java

+ 8 - 0
AutomatedTesting/CMakeLists.txt

@@ -9,4 +9,12 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 #
 #
 
 
+file(READ "${CMAKE_CURRENT_LIST_DIR}/project.json" project_json)
+
+string(JSON project_target_name ERROR_VARIABLE json_error GET ${project_json} "project_name")
+if(${json_error})
+    message(FATAL_ERROR "Unable to read key 'project_name' from 'project.json'")
+endif()
+
+set_property(GLOBAL APPEND PROPERTY LY_PROJECTS_TARGET_NAME ${project_target_name})
 add_subdirectory(Gem)
 add_subdirectory(Gem)

+ 0 - 197
AutomatedTesting/Config/Editor.xml

@@ -1,197 +0,0 @@
-<ObjectStream version="1">
-	<Class name="ComponentApplication::Descriptor" version="2" type="{70277A3E-2AF5-4309-9BBF-6161AFBDE792}">
-		<Class name="bool" field="useExistingAllocator" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="grabAllMemory" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="allocationRecords" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="allocationRecordsSaveNames" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="allocationRecordsAttemptDecodeImmediately" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="int" field="recordingMode" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
-		<Class name="AZ::u64" field="stackRecordLevels" value="5" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		<Class name="bool" field="autoIntegrityCheck" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="markUnallocatedMemory" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="doNotUsePools" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="enableScriptReflection" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="unsigned int" field="pageSize" value="65536" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-		<Class name="unsigned int" field="poolPageSize" value="4096" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-		<Class name="unsigned int" field="blockAlignment" value="65536" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-		<Class name="AZ::u64" field="blockSize" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		<Class name="AZ::u64" field="reservedOS" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		<Class name="AZ::u64" field="reservedDebug" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		<Class name="bool" field="enableDrilling" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="useOverrunDetection" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="useMalloc" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="AZStd::vector" field="allocatorRemappings" type="{82897F6E-6389-5BEF-B427-761DB35AC1CC}"/>
-		<Class name="AZStd::vector" field="modules" type="{8E779F80-AEAA-565B-ABB1-DE10B18CF995}">
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Maestro.Editor.3b9a978ed6f742a1acb99f74379a342c.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.TextureAtlas.5a149b6b3c964064bd4970f0e92f72e2.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.LmbrCentral.Editor.ff06785f7145416b9d46fde39098cb0c.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.LyShine.Editor.0fefab3f13364722b2eab3b96ce2bf20.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.HttpRequestor.28479e255bde466e91fc34eec808d9c7.v1.0.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ScriptEvents.Editor.32d8ba21703e4bbbb08487366e48dd69.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ExpressionEvaluation.4c6f9df57ca2468f93c8d860ee6a1167.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.AssetValidation.5a5c3c10b91d4b4ea8baef474c5b5d49.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Gestures.6056556b6088413984309c4a413593ad.v1.0.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.CertificateManager.659cffff33b14a10835bafc6ea623f98.v0.0.1" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.DebugDraw.Editor.66239f50bf754354b514c850c8b841fb.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.AudioSystem.Editor.6f63f2b6d07f4b89b4b7c86ebee7feb8.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.GameLift.76de765796504906b73be7365a9bff06.v2.0.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.SceneProcessing.Editor.7c2578f634df4345aca98d671e39b8ab.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.GraphCanvas.Editor.875b6fcbdeea44deaae7984ad9bb6cdc.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.InAppPurchases.92fe57eae7d3402a90761973678c079a.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.AutomatedTesting.afc25e1593194d6283d9ff744ab6d5a1.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.EditorPythonBindings.Editor.b658359393884c4381c2fe2952b1472a.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Metastream.c02d7efe05134983b5699d9ee7594c3a.v1.0.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.WhiteBox.Editor.c5833dbda2e045d3a5f16b7414280c27.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ImageProcessing.Editor.eeffbd9211cf4ce0b5cc73696b427cbe.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.TestAssetBuilder.Editor.f5c92f1560714010ba30467d93feecef.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Camera.Editor.f910686b6725452fbfc4671f95f733c6.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.EMotionFX.Editor.044a63ea67d04479aa5daf62ded9d9ca.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.GraphModel.Editor.0844f64a3acf4f5abf3a535dc9b63bc9.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.PhysX.Editor.4e08125824434932a0fe3717259caa47.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.CameraFramework.54f2763fe191432fa681ce4a354eedf5.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.SurfaceData.Editor.5de82d29d6094bfe97c1a4d35fcd5fbe.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.AudioEngineWwise.Editor.67a80e2ac865406c990f2715feb55f7f.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.StartingPointMovement.73d8779dc28a4123b7c9ed76217464af.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.StartingPointCamera.834070b9537d44df83559e2045c3859f.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ScriptCanvasGem.Editor.869a0d0ec11a45c299917d45c81555e6.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.GradientSignal.Editor.8825563d9d964ec3be3bab681f3bd9f2.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ImGui.Editor.bab8807a1bc646b3909f3cc200ffeedf.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ChatPlay.bfbc60c63ffd4b00927003735b26ce99.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.TouchBending.Editor.c58d2057f3724b22ae0df0be68a4e316.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.FastNoise.Editor.c5f23032407f49ca8d8de1733423565c.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.LyShineExamples.c7935ecf5e8047fe8ca947b34b11cadb.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Vegetation.Editor.f394e7cf54424bba89615381bba9511b.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.StartingPointInput.Editor.09f4bedeee614358bc36788e77f97e51.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.LandscapeCanvas.Editor.19c2b2d5018940108baf252934b8e6bf.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ScriptCanvasPhysics.1c27519a4dda4ffaaeebf91514e5b1e8.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.PhysXDebug.Editor.516145e2d9904b13813f1b54605e26a6.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-		</Class>
-	</Class>
-	<Class name="AZ::Entity" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
-		<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-			<Class name="AZ::u64" field="id" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		</Class>
-		<Class name="AZStd::string" field="Name" value="SystemEntity" type="{EF8FF807-DDEE-4EB0-B678-4CA3A2C490A4}"/>
-		<Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="AZStd::vector" field="Components" type="{2BADE35A-6F1B-4698-B2BC-3373D010020C}">
-			<Class name="PhysicsSystemComponent" field="element" value="" version="1" type="{1586DBA1-F5F0-49AB-9F59-AE62C0E60AE0}">
-				<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-					<Class name="AZ::u64" field="Id" value="5881970355815182227" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-			</Class>
-			<Class name="NavigationSystemComponent" field="element" value="" version="1" type="{3D27484B-00C4-4F3F-9605-2BF3E5C317FF}">
-				<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-					<Class name="AZ::u64" field="Id" value="3408791856679455729" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-			</Class>
-			<Class name="EditorSelectionAccentSystemComponent" field="element" value="" type="{6E0F0E2C-1FE5-4AFB-9672-DC92B3D2D844}">
-				<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-					<Class name="AZ::u64" field="Id" value="4281709857282575192" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-			</Class>
-			<Class name="AudioSystemComponent" field="element" version="1" type="{666E28D2-FC99-4D41-861D-3758C5070653}">
-				<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-					<Class name="AZ::u64" field="Id" value="4028172539943260142" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-			</Class>
-			<Class name="LyShineSystemComponent" field="element" value="" type="{B0C78B8D-1E5B-47D7-95D0-EC69C0513804}">
-				<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-					<Class name="AZ::u64" field="Id" value="13584318858523138243" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-			</Class>
-			<Class name="LyEditorMetricsSystemComponent" field="element" value="" type="{B8C74085-F6B7-4E2F-8135-78C991CC53C5}">
-				<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-					<Class name="AZ::u64" field="Id" value="8970396848016072155" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-			</Class>
-			<Class name="StereoRendererComponent" field="element" version="1" type="{BBFE0965-5564-4739-8219-AFE8209A5E57}"/>
-		</Class>
-	</Class>
-</ObjectStream>
-

+ 0 - 179
AutomatedTesting/Config/Game.xml

@@ -1,179 +0,0 @@
-<ObjectStream version="1">
-	<Class name="ComponentApplication::Descriptor" version="2" type="{70277A3E-2AF5-4309-9BBF-6161AFBDE792}">
-		<Class name="bool" field="useExistingAllocator" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="grabAllMemory" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="allocationRecords" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="allocationRecordsSaveNames" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="allocationRecordsAttemptDecodeImmediately" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="int" field="recordingMode" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
-		<Class name="AZ::u64" field="stackRecordLevels" value="5" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		<Class name="bool" field="autoIntegrityCheck" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="markUnallocatedMemory" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="doNotUsePools" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="enableScriptReflection" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="unsigned int" field="pageSize" value="65536" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-		<Class name="unsigned int" field="poolPageSize" value="4096" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-		<Class name="unsigned int" field="blockAlignment" value="65536" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-		<Class name="AZ::u64" field="blockSize" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		<Class name="AZ::u64" field="reservedOS" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		<Class name="AZ::u64" field="reservedDebug" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		<Class name="bool" field="enableDrilling" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="useOverrunDetection" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="useMalloc" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="AZStd::vector" field="allocatorRemappings" type="{82897F6E-6389-5BEF-B427-761DB35AC1CC}"/>
-		<Class name="AZStd::vector" field="modules" type="{8E779F80-AEAA-565B-ABB1-DE10B18CF995}">
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Maestro.3b9a978ed6f742a1acb99f74379a342c.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.TextureAtlas.5a149b6b3c964064bd4970f0e92f72e2.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.LmbrCentral.ff06785f7145416b9d46fde39098cb0c.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.LyShine.0fefab3f13364722b2eab3b96ce2bf20.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.HttpRequestor.28479e255bde466e91fc34eec808d9c7.v1.0.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ScriptEvents.32d8ba21703e4bbbb08487366e48dd69.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ExpressionEvaluation.4c6f9df57ca2468f93c8d860ee6a1167.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.AssetValidation.5a5c3c10b91d4b4ea8baef474c5b5d49.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Gestures.6056556b6088413984309c4a413593ad.v1.0.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.CertificateManager.659cffff33b14a10835bafc6ea623f98.v0.0.1" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.DebugDraw.66239f50bf754354b514c850c8b841fb.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.AudioSystem.6f63f2b6d07f4b89b4b7c86ebee7feb8.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.GameLift.76de765796504906b73be7365a9bff06.v2.0.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.GraphCanvas.875b6fcbdeea44deaae7984ad9bb6cdc.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.InAppPurchases.92fe57eae7d3402a90761973678c079a.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.AutomatedTesting.afc25e1593194d6283d9ff744ab6d5a1.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Metastream.c02d7efe05134983b5699d9ee7594c3a.v1.0.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.WhiteBox.c5833dbda2e045d3a5f16b7414280c27.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Camera.f910686b6725452fbfc4671f95f733c6.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.EMotionFX.044a63ea67d04479aa5daf62ded9d9ca.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.PhysX.4e08125824434932a0fe3717259caa47.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.CameraFramework.54f2763fe191432fa681ce4a354eedf5.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.SurfaceData.5de82d29d6094bfe97c1a4d35fcd5fbe.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.AudioEngineWwise.67a80e2ac865406c990f2715feb55f7f.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.StartingPointMovement.73d8779dc28a4123b7c9ed76217464af.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.StartingPointCamera.834070b9537d44df83559e2045c3859f.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ScriptCanvasGem.869a0d0ec11a45c299917d45c81555e6.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.GradientSignal.8825563d9d964ec3be3bab681f3bd9f2.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ImGui.bab8807a1bc646b3909f3cc200ffeedf.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ChatPlay.bfbc60c63ffd4b00927003735b26ce99.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.TouchBending.c58d2057f3724b22ae0df0be68a4e316.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.FastNoise.c5f23032407f49ca8d8de1733423565c.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.LyShineExamples.c7935ecf5e8047fe8ca947b34b11cadb.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Vegetation.f394e7cf54424bba89615381bba9511b.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.StartingPointInput.09f4bedeee614358bc36788e77f97e51.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ScriptCanvasPhysics.1c27519a4dda4ffaaeebf91514e5b1e8.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.PhysXDebug.516145e2d9904b13813f1b54605e26a6.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-		</Class>
-	</Class>
-	<Class name="AZ::Entity" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
-		<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-			<Class name="AZ::u64" field="id" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		</Class>
-		<Class name="AZStd::string" field="Name" value="SystemEntity" type="{EF8FF807-DDEE-4EB0-B678-4CA3A2C490A4}"/>
-		<Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="AZStd::vector" field="Components" type="{2BADE35A-6F1B-4698-B2BC-3373D010020C}">
-			<Class name="PhysicsSystemComponent" field="element" value="" version="1" type="{1586DBA1-F5F0-49AB-9F59-AE62C0E60AE0}">
-				<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-					<Class name="AZ::u64" field="Id" value="14545574550664822512" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-			</Class>
-			<Class name="NavigationSystemComponent" field="element" value="" version="1" type="{3D27484B-00C4-4F3F-9605-2BF3E5C317FF}">
-				<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-					<Class name="AZ::u64" field="Id" value="9809863829757322975" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-			</Class>
-			<Class name="LyShineSystemComponent" field="element" value="" type="{B0C78B8D-1E5B-47D7-95D0-EC69C0513804}">
-				<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-					<Class name="AZ::u64" field="Id" value="3706545825063126910" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-			</Class>
-			<Class name="AudioSystemComponent" field="element" version="1" type="{666E28D2-FC99-4D41-861D-3758C5070653}">
-				<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-					<Class name="AZ::u64" field="Id" value="17265601292746528732" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-			</Class>
-			<Class name="StereoRendererComponent" field="element" version="1" type="{BBFE0965-5564-4739-8219-AFE8209A5E57}"/>
-			<Class name="LmbrCentralSystemComponent" field="element" value="" version="1" type="{CE249D37-C1D6-4A64-932D-C937B0EC2B8C}">
-				<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-					<Class name="AZ::u64" field="Id" value="17265313386362322770" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-			</Class>
-			<Class name="AssetDatabaseComponent" field="element" value="" version="1" type="{D5A73BCC-0098-4D1E-8FE4-C86101E374AC}">
-				<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-					<Class name="AZ::u64" field="Id" value="18338415854038604706" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-			</Class>
-		</Class>
-	</Class>
-</ObjectStream>
-

+ 0 - 136
AutomatedTesting/Config/Server.xml

@@ -1,136 +0,0 @@
-<ObjectStream version="3">
-	<Class name="ComponentApplication::Descriptor" version="2" type="{70277A3E-2AF5-4309-9BBF-6161AFBDE792}">
-		<Class name="bool" field="useExistingAllocator" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="grabAllMemory" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="allocationRecords" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="allocationRecordsSaveNames" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="allocationRecordsAttemptDecodeImmediately" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="int" field="recordingMode" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
-		<Class name="AZ::u64" field="stackRecordLevels" value="5" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		<Class name="bool" field="autoIntegrityCheck" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="markUnallocatedMemory" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="doNotUsePools" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="enableScriptReflection" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="unsigned int" field="pageSize" value="65536" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-		<Class name="unsigned int" field="poolPageSize" value="4096" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-		<Class name="unsigned int" field="blockAlignment" value="65536" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-		<Class name="AZ::u64" field="blockSize" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		<Class name="AZ::u64" field="reservedOS" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		<Class name="AZ::u64" field="reservedDebug" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		<Class name="bool" field="enableDrilling" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="useOverrunDetection" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="useMalloc" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="AZStd::vector" field="allocatorRemappings" type="{82897F6E-6389-5BEF-B427-761DB35AC1CC}"/>
-		<Class name="AZStd::vector" field="modules" type="{8E779F80-AEAA-565B-ABB1-DE10B18CF995}">
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Maestro.3b9a978ed6f742a1acb99f74379a342c.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.TextureAtlas.5a149b6b3c964064bd4970f0e92f72e2.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.LmbrCentral.ff06785f7145416b9d46fde39098cb0c.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.LyShine.0fefab3f13364722b2eab3b96ce2bf20.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.HttpRequestor.28479e255bde466e91fc34eec808d9c7.v1.0.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ScriptEvents.32d8ba21703e4bbbb08487366e48dd69.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ExpressionEvaluation.4c6f9df57ca2468f93c8d860ee6a1167.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.AssetValidation.5a5c3c10b91d4b4ea8baef474c5b5d49.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Gestures.6056556b6088413984309c4a413593ad.v1.0.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.CertificateManager.659cffff33b14a10835bafc6ea623f98.v0.0.1" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.DebugDraw.66239f50bf754354b514c850c8b841fb.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.AudioSystem.6f63f2b6d07f4b89b4b7c86ebee7feb8.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.GameLift.76de765796504906b73be7365a9bff06.v2.0.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.GraphCanvas.875b6fcbdeea44deaae7984ad9bb6cdc.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.InAppPurchases.92fe57eae7d3402a90761973678c079a.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.AutomatedTesting.afc25e1593194d6283d9ff744ab6d5a1.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Metastream.c02d7efe05134983b5699d9ee7594c3a.v1.0.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.WhiteBox.c5833dbda2e045d3a5f16b7414280c27.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.Camera.f910686b6725452fbfc4671f95f733c6.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.EMotionFX.044a63ea67d04479aa5daf62ded9d9ca.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.PhysX.4e08125824434932a0fe3717259caa47.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.PhysXCharacters.50f9ae1e09ac471bbd9d86ca8063ddf9.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.CameraFramework.54f2763fe191432fa681ce4a354eedf5.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.AudioEngineWwise.67a80e2ac865406c990f2715feb55f7f.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.StartingPointMovement.73d8779dc28a4123b7c9ed76217464af.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.StartingPointCamera.834070b9537d44df83559e2045c3859f.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ScriptCanvasGem.869a0d0ec11a45c299917d45c81555e6.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ImGui.bab8807a1bc646b3909f3cc200ffeedf.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ChatPlay.bfbc60c63ffd4b00927003735b26ce99.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.LyShineExamples.c7935ecf5e8047fe8ca947b34b11cadb.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.StartingPointInput.09f4bedeee614358bc36788e77f97e51.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.ScriptCanvasPhysics.1c27519a4dda4ffaaeebf91514e5b1e8.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-			<Class name="DynamicModuleDescriptor" field="element" type="{D2932FA3-9942-4FD2-A703-2E750F57C003}">
-				<Class name="AZStd::string" field="dynamicLibraryPath" value="Gem.PhysXDebug.516145e2d9904b13813f1b54605e26a6.v0.1.0" type="{189CC2ED-FDDE-5680-91D4-9F630A79187F}"/>
-			</Class>
-		</Class>
-	</Class>
-	<Class name="AZ::Entity" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
-		<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-			<Class name="AZ::u64" field="id" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		</Class>
-		<Class name="AZStd::string" field="Name" value="SystemEntity" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		<Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"/>
-		<Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-		<Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-	</Class>
-</ObjectStream>
-

+ 0 - 16
AutomatedTesting/Gem/AssetProcessorGemConfig.ini

@@ -1,16 +0,0 @@
-; The PythonTest folder contains benchmarksettings test assets that should only get processed when
-; the test is run, and the assets are temporarily copied to a separate folder.
-[Exclude PythonTest Benchmark Settings Assets]
-pattern=.*\\/PythonTests\\/.*benchmarksettings
-
-[Exclude fbx_tests]
-pattern=.*\\/fbx_tests\\/assets\\/.*
-
-[Exclude wwise_bank_dependency_tests]
-pattern=.*\\/wwise_bank_dependency_tests\\/assets\\/.*
-
-[Exclude AssetProcessorTestAssets]
-pattern=.*\\/asset_processor_tests\\/assets\\/.*
-
-[Exclude Restricted AssetProcessorTestAssets]
-pattern=.*\\/asset_processor_tests\\/restricted\\/.*

+ 23 - 0
AutomatedTesting/Gem/AssetProcessorGemConfig.setreg

@@ -0,0 +1,23 @@
+{
+    "Amazon": {
+        "AssetProcessor": {
+            "Settings": {
+                "Exclude PythonTest Benchmark Settings Assets": {
+                    "pattern": ".*\\\\/PythonTests\\\\/.*benchmarksettings"
+                },
+                "Exclude fbx_tests": {
+                    "pattern": ".*\\\\/fbx_tests\\\\/assets\\\\/.*"
+                },
+                "Exclude wwise_bank_dependency_tests": {
+                    "pattern": ".*\\\\/wwise_bank_dependency_tests\\\\/assets\\\\/.*"
+                },
+                "Exclude AssetProcessorTestAssets": {
+                    "pattern": ".*\\\\/asset_processor_tests\\\\/assets\\\\/.*"
+                },
+                "Exclude Restricted AssetProcessorTestAssets": {
+                    "pattern": ".*\\\\/asset_processor_tests\\\\/restricted\\\\/.*"
+                }
+            }
+        }
+    }
+}

+ 36 - 4
AutomatedTesting/Gem/PythonTests/CMakeLists.txt

@@ -30,6 +30,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
             Legacy::CryRenderNULL
             Legacy::CryRenderNULL
             AZ::AssetProcessor
             AZ::AssetProcessor
             AutomatedTesting.Assets
             AutomatedTesting.Assets
+        COMPONENT
+            Physics
     )
     )
     ly_add_pytest(
     ly_add_pytest(
         NAME AutomatedTesting::PhysicsTests_Sandbox
         NAME AutomatedTesting::PhysicsTests_Sandbox
@@ -42,6 +44,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
             Legacy::CryRenderNULL
             Legacy::CryRenderNULL
             AZ::AssetProcessor
             AZ::AssetProcessor
             AutomatedTesting.Assets
             AutomatedTesting.Assets
+        COMPONENT
+            Physics
     )
     )
 endif()
 endif()
 
 
@@ -49,7 +53,7 @@ endif()
 if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
 if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
     ly_add_pytest(
     ly_add_pytest(
         NAME AutomatedTesting::ScriptCanvasTests
         NAME AutomatedTesting::ScriptCanvasTests
-        TEST_SUITE main
+        TEST_SUITE periodic
         TEST_SERIAL
         TEST_SERIAL
         PATH ${CMAKE_CURRENT_LIST_DIR}/scripting/TestSuite_Active.py
         PATH ${CMAKE_CURRENT_LIST_DIR}/scripting/TestSuite_Active.py
         TIMEOUT 3600
         TIMEOUT 3600
@@ -58,6 +62,20 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
             Legacy::CryRenderNULL
             Legacy::CryRenderNULL
             AZ::AssetProcessor
             AZ::AssetProcessor
             AutomatedTesting.Assets
             AutomatedTesting.Assets
+        COMPONENT
+            ScriptCanvas
+    )
+    ly_add_pytest(
+        NAME AutomatedTesting::ScriptCanvasTests_Sandbox
+        TEST_SUITE sandbox
+        TEST_SERIAL
+        PATH ${CMAKE_CURRENT_LIST_DIR}/scripting/TestSuite_Sandbox.py
+        TIMEOUT 3600
+        RUNTIME_DEPENDENCIES
+            Legacy::Editor
+            Legacy::CryRenderNULL
+            AZ::AssetProcessor
+            AutomatedTesting.Assets
     )
     )
 endif()
 endif()
 
 
@@ -74,6 +92,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
             Legacy::CryRenderNULL
             Legacy::CryRenderNULL
             AZ::AssetProcessor
             AZ::AssetProcessor
             AutomatedTesting.Assets
             AutomatedTesting.Assets
+        COMPONENT
+            WhiteBox
     )
     )
 endif()
 endif()
 
 
@@ -108,7 +128,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
             AZ::AssetProcessor
             AZ::AssetProcessor
             AutomatedTesting.Assets
             AutomatedTesting.Assets
             Gem::EditorPythonBindings.Editor
             Gem::EditorPythonBindings.Editor
-            COMPONENT TestTools
+        COMPONENT TestTools
     )
     )
 endif()
 endif()
 
 
@@ -136,7 +156,6 @@ include(${pal_dir}/PAL_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
 if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_LARGE_WORLDS_TEST_SUPPORTED)
 if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_LARGE_WORLDS_TEST_SUPPORTED)
 
 
 ## DynVeg ##
 ## DynVeg ##
-
     ly_add_pytest(
     ly_add_pytest(
         NAME DynamicVegetationTests_Main_NoGPU
         NAME DynamicVegetationTests_Main_NoGPU
         TEST_SERIAL
         TEST_SERIAL
@@ -150,6 +169,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
             AutomatedTesting.GameLauncher
             AutomatedTesting.GameLauncher
             AutomatedTesting.Assets
             AutomatedTesting.Assets
             Legacy::CryRenderNULL
             Legacy::CryRenderNULL
+        COMPONENT
+            LargeWorlds
     )
     )
 
 
     ly_add_pytest(
     ly_add_pytest(
@@ -165,6 +186,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
             AutomatedTesting.GameLauncher
             AutomatedTesting.GameLauncher
             AutomatedTesting.Assets
             AutomatedTesting.Assets
             Legacy::CryRenderNULL
             Legacy::CryRenderNULL
+        COMPONENT
+            LargeWorlds
     )
     )
 
 
     ly_add_pytest(
     ly_add_pytest(
@@ -179,10 +202,11 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
             Legacy::Editor
             Legacy::Editor
             AutomatedTesting.Assets
             AutomatedTesting.Assets
             Legacy::CryRenderNULL
             Legacy::CryRenderNULL
+        COMPONENT
+            LargeWorlds
     )
     )
 
 
 ## LandscapeCanvas ##
 ## LandscapeCanvas ##
-
     ly_add_pytest(
     ly_add_pytest(
         NAME LandscapeCanvasTests_Main
         NAME LandscapeCanvasTests_Main
         TEST_SERIAL
         TEST_SERIAL
@@ -194,6 +218,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
            Legacy::Editor
            Legacy::Editor
            AutomatedTesting.Assets
            AutomatedTesting.Assets
            Legacy::CryRenderNULL
            Legacy::CryRenderNULL
+        COMPONENT
+            LargeWorlds
     )
     )
 
 
 ## GradientSignal ##
 ## GradientSignal ##
@@ -209,6 +235,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
             Legacy::Editor
             Legacy::Editor
             AutomatedTesting.Assets
             AutomatedTesting.Assets
             Legacy::CryRenderNULL
             Legacy::CryRenderNULL
+        COMPONENT
+            LargeWorlds
     )
     )
 
 
     ly_add_pytest(
     ly_add_pytest(
@@ -222,6 +250,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
             Legacy::Editor
             Legacy::Editor
             AutomatedTesting.Assets
             AutomatedTesting.Assets
             Legacy::CryRenderNULL
             Legacy::CryRenderNULL
+        COMPONENT
+            LargeWorlds
     )
     )
 
 
 endif()
 endif()
@@ -239,6 +269,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
             Legacy::CryRenderNULL
             Legacy::CryRenderNULL
             AZ::AssetProcessor
             AZ::AssetProcessor
             AutomatedTesting.Assets
             AutomatedTesting.Assets
+        COMPONENT
+            Editor
     )
     )
 endif()
 endif()
 
 

+ 6 - 6
AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_all_platforms_setup_fixture.py

@@ -24,7 +24,7 @@ from . import ap_setup_fixture as ap_setup_fixture
 def ap_all_platforms_setup_fixture(request, workspace, ap_setup_fixture) -> Dict[str, str]:
 def ap_all_platforms_setup_fixture(request, workspace, ap_setup_fixture) -> Dict[str, str]:
 
 
     dev_dir = os.path.join(workspace.paths.dev())
     dev_dir = os.path.join(workspace.paths.dev())
-    cache_dir = os.path.join(dev_dir, "Cache")
+    cache_dir = workspace.paths.cache()
 
 
     # add some useful locations
     # add some useful locations
     resources = ap_setup_fixture
     resources = ap_setup_fixture
@@ -33,11 +33,11 @@ def ap_all_platforms_setup_fixture(request, workspace, ap_setup_fixture) -> Dict
     resources["platform_cache"] = os.path.join(workspace.paths.platform_cache(), workspace.project.lower())
     resources["platform_cache"] = os.path.join(workspace.paths.platform_cache(), workspace.project.lower())
 
 
     # Specific platform cache locations
     # Specific platform cache locations
-    resources["pc_cache_location"] = os.path.join(cache_dir, workspace.project, "pc")
-    resources["es3_cache_location"] = os.path.join(cache_dir, workspace.project, "es3")
-    resources["ios_cache_location"] = os.path.join(cache_dir, workspace.project, "ios")
-    resources["osx_gl_cache_location"] = os.path.join(cache_dir, workspace.project, "osx_gl")
-    resources["provo_cache_location"] = os.path.join(cache_dir, workspace.project, "provo")
+    resources["pc_cache_location"] = os.path.join(cache_dir, "pc")
+    resources["es3_cache_location"] = os.path.join(cache_dir, "es3")
+    resources["ios_cache_location"] = os.path.join(cache_dir, "ios")
+    resources["osx_gl_cache_location"] = os.path.join(cache_dir, "osx_gl")
+    resources["provo_cache_location"] = os.path.join(cache_dir, "provo")
     resources["all_platforms"] = ["pc", "es3", "ios", "osx_gl", "provo"]
     resources["all_platforms"] = ["pc", "es3", "ios", "osx_gl", "provo"]
 
 
     return resources
     return resources

+ 1 - 1
AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_external_project_setup_fixture.py

@@ -52,7 +52,7 @@ def ap_external_project_setup_fixture(request, workspace) -> Dict:
     paths = mock()
     paths = mock()
     paths.asset_processor = lambda: resources["ap_path"]
     paths.asset_processor = lambda: resources["ap_path"]
     paths.asset_processor_batch = lambda: resources["ap_batch_path"]
     paths.asset_processor_batch = lambda: resources["ap_batch_path"]
-    paths.asset_processor_config_file = lambda: os.path.join(resources["project_dir"], "AssetProcessorConfig.ini")
+    paths.asset_processor_config_file = lambda: os.path.join(resources["project_dir"], "AssetProcessorConfig.setreg")
     mock_workspace.paths = paths
     mock_workspace.paths = paths
     resources["external_workspace"] = mock_workspace
     resources["external_workspace"] = mock_workspace
 
 

+ 3 - 2
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests_2.py

@@ -163,7 +163,7 @@ class TestsAssetProcessorBatch_AllPlatforms(object):
         assert errors == 0, f"There were {errors} asset processing errors"
         assert errors == 0, f"There were {errors} asset processing errors"
 
 
         # Check that project cache was created (DNE until AP makes it)
         # Check that project cache was created (DNE until AP makes it)
-        project_cache = os.path.join(external_resources["project_dir"], "Cache", external_resources["project_name"])
+        project_cache = os.path.join(external_resources["project_dir"], "Cache")
         assert os.path.exists(project_cache), f"{project_cache} was not created by AP"
         assert os.path.exists(project_cache), f"{project_cache} was not created by AP"
 
 
         # Clean up external project
         # Clean up external project
@@ -273,7 +273,8 @@ class TestsAssetProcessorBatch_Windows(object):
         "AssetProcessor: Error: Platform in config file or command line 'notaplatform'" should be present in the logs
         "AssetProcessor: Error: Platform in config file or command line 'notaplatform'" should be present in the logs
         """
         """
         asset_processor.create_temp_asset_root()
         asset_processor.create_temp_asset_root()
-        error_search_terms = "AssetProcessor: Error: Platform in config file or command line 'notaplatform'"
+        error_search_terms = 'AssetProcessor: Error: The list of enabled platforms in the settings registry does not contain platform ' \
+                             '"notaplatform"'
         # Run APBatch expecting it to fail
         # Run APBatch expecting it to fail
         asset_processor.run_and_check_output(True, error_search_terms, platforms='notaplatform')
         asset_processor.run_and_check_output(True, error_search_terms, platforms='notaplatform')
 
 

+ 15 - 19
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests_2.py

@@ -25,7 +25,7 @@ import ly_test_tools.environment.waiter as waiter
 import ly_test_tools.environment.file_system as fs
 import ly_test_tools.environment.file_system as fs
 import ly_test_tools.environment.process_utils as process_utils
 import ly_test_tools.environment.process_utils as process_utils
 import ly_test_tools.launchers.launcher_helper as launcher_helper
 import ly_test_tools.launchers.launcher_helper as launcher_helper
-from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP
+from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP, ASSET_PROCESSOR_SETTINGS_ROOT_KEY
 
 
 # Import fixtures
 # Import fixtures
 from ..ap_fixtures.asset_processor_fixture import asset_processor as asset_processor
 from ..ap_fixtures.asset_processor_fixture import asset_processor as asset_processor
@@ -136,7 +136,7 @@ class TestsAssetProcessorGUI_WindowsAndMac(object):
         # Validate that no fatal errors (crashes) are reported within a certain time frame (10 seconds timeout)
         # Validate that no fatal errors (crashes) are reported within a certain time frame (10 seconds timeout)
         #   This applies to AP and GameLauncher.exe
         #   This applies to AP and GameLauncher.exe
         time.sleep(CHECK_ALIVE_SECONDS)
         time.sleep(CHECK_ALIVE_SECONDS)
-        launcher_name = f"{workspace.project.title()}Launcher"
+        launcher_name = f"{workspace.project.title()}.GameLauncher"
         # fmt:off
         # fmt:off
         assert process_utils.process_exists(launcher_name, ignore_extensions=True), \
         assert process_utils.process_exists(launcher_name, ignore_extensions=True), \
             f"{launcher_name} was not live during the check."
             f"{launcher_name} was not live during the check."
@@ -221,23 +221,20 @@ class TestsAssetProcessorGUI_AllPlatforms(object):
 
 
         assert not test_assets_added_to_cache(), "Test assets are present in cache before adding scan folder"
         assert not test_assets_added_to_cache(), "Test assets are present in cache before adding scan folder"
 
 
-        # Add test assets folder in dev to AP config file (AssetProcessorPlatformConfig.ini) to be scanned
-        ap_config_file = os.path.join(asset_processor.temp_asset_root(), 'AssetProcessorPlatformConfig.ini')
-        config = configparser.ConfigParser()
-        config.read(ap_config_file)
-        config["ScanFolder C4874115"] = {
-            "watch": "@ROOT@/C4874115",
-            "output": "C4874115",
-            "recursive": "1",
-            "order": "5000",
-        }
-        with open(ap_config_file, "w") as configfile:
-            config.write(configfile)
+        # Supply an additional scan folder for the test via the settings registry regset parameters
+        test_scan_folder_params = []
+
+        test_scan_folder_root_key = f"{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/ScanFolder C4874115"
+        test_scan_folder_params.append(f'--regset="{test_scan_folder_root_key}/watch=@ROOT@/C4874115"')
+        test_scan_folder_params.append(f'--regset="{test_scan_folder_root_key}/output=C4874115"')
+        test_scan_folder_params.append(f'--regset="{test_scan_folder_root_key}/recursive=1"')
+        test_scan_folder_params.append(f'--regset="{test_scan_folder_root_key}/order=5000"')
 
 
         # Run AP GUI and read the config file we just modified to pick up our scan folder
         # Run AP GUI and read the config file we just modified to pick up our scan folder
         # Pass in a pattern so we don't spend time processing unrelated folders
         # Pass in a pattern so we don't spend time processing unrelated folders
         result, _ = asset_processor.gui_process(quitonidle=True, add_config_scan_folders=True,
         result, _ = asset_processor.gui_process(quitonidle=True, add_config_scan_folders=True,
-                                                scan_folder_pattern="*C4874115*")
+                                                scan_folder_pattern="*C4874115*",
+                                                extra_params=test_scan_folder_params)
         assert result, "AP GUI failed"
         assert result, "AP GUI failed"
 
 
         # Verify test assets processed into cache after adding scan folder
         # Verify test assets processed into cache after adding scan folder
@@ -255,10 +252,9 @@ class TestsAssetProcessorGUI_AllPlatforms(object):
         test_ip_address = "1.1.1.1"  # an IP address without Asset Processor
         test_ip_address = "1.1.1.1"  # an IP address without Asset Processor
 
 
         asset_processor.create_temp_asset_root()
         asset_processor.create_temp_asset_root()
-        # Edit remote_ip setting in bootstrap.cfg to an IP address without Asset Processor
-        workspace.settings.modify_bootstrap_setting("remote_ip", test_ip_address,
-                                                    bootstrap_path=os.path.join(asset_processor.temp_asset_root(),
-                                                                                'bootstrap.cfg'))
+        # Set the remote_ip setting through the settings registry to an IP address without Asset Processor
+        extra_params = []
+        extra_params.append(f'--regset="/Amazon/AzCore/Bootstrap/remote_ip={test_ip_address}"')
 
 
         # Run AP Gui to verify that assets process regardless of the new address
         # Run AP Gui to verify that assets process regardless of the new address
         result, _ = asset_processor.gui_process(quitonidle=True)
         result, _ = asset_processor.gui_process(quitonidle=True)

+ 1 - 1
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/missing_dependency_tests.py

@@ -64,7 +64,7 @@ class TestsMissingDependencies_WindowsAndMac(object):
         self._missing_dep_helper = missing_dep_helper
         self._missing_dep_helper = missing_dep_helper
         self._asset_processor.create_temp_asset_root()
         self._asset_processor.create_temp_asset_root()
         self._asset_processor.add_source_folder_assets(f"AutomatedTesting\\TestAssets")
         self._asset_processor.add_source_folder_assets(f"AutomatedTesting\\TestAssets")
-        missing_dep_helper.asset_db = os.path.join(asset_processor.temp_asset_root(), "Cache", workspace.project,
+        missing_dep_helper.asset_db = os.path.join(asset_processor.temp_asset_root(), "Cache",
                                                    "assetdb.sqlite")
                                                    "assetdb.sqlite")
         self._asset_processor.add_source_folder_assets(f"{self._workspace.project}\\Slices")
         self._asset_processor.add_source_folder_assets(f"{self._workspace.project}\\Slices")
         self._asset_processor.add_source_folder_assets(f"{self._workspace.project}\\Materials")
         self._asset_processor.add_source_folder_assets(f"{self._workspace.project}\\Materials")

+ 2 - 2
AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/fbx_tests.py

@@ -597,9 +597,9 @@ class TestsFBX_AllPlatforms(object):
 
 
         # Load the asset database.
         # Load the asset database.
         db_path = os.path.join(asset_processor.temp_asset_root(), "Cache",
         db_path = os.path.join(asset_processor.temp_asset_root(), "Cache",
-                               workspace.project, "assetdb.sqlite")
+                               "assetdb.sqlite")
         cache_root = os.path.dirname(os.path.join(asset_processor.temp_asset_root(), "Cache",
         cache_root = os.path.dirname(os.path.join(asset_processor.temp_asset_root(), "Cache",
-                               workspace.project, ASSET_PROCESSOR_PLATFORM_MAP[workspace.asset_processor_platform]))
+                               ASSET_PROCESSOR_PLATFORM_MAP[workspace.asset_processor_platform]))
 
 
         if blackbox_params.scene_debug_file:
         if blackbox_params.scene_debug_file:
             debug_graph_path = os.path.join(asset_processor.project_test_cache_folder(), blackbox_params.scene_debug_file)
             debug_graph_path = os.path.join(asset_processor.project_test_cache_folder(), blackbox_params.scene_debug_file)

+ 3 - 2
AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py

@@ -131,8 +131,9 @@ class TestAutomationBase:
                         crash_info = f.read()
                         crash_info = f.read()
                 except Exception as ex:
                 except Exception as ex:
                     crash_info += f"\n{str(ex)}"
                     crash_info += f"\n{str(ex)}"
-                        
-                error_str = f"Editor.exe crashed, return code: 0x{return_code:0X}\n\nCrash log:\n{crash_info}"
+
+                return_code_str = f"0x{return_code:0X}" if isinstance(return_code, int) else "None"
+                error_str = f"Editor.exe crashed, return code: {return_code_str}\n\nCrash log:\n{crash_info}"
                 errors.append(TestRunError("CRASH", error_str))
                 errors.append(TestRunError("CRASH", error_str))
         
         
         self.test_times[testcase_name] = time.time() - test_starttime
         self.test_times[testcase_name] = time.time() - test_starttime

+ 2 - 8
AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Active.py

@@ -19,16 +19,11 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesti
 
 
 from base import TestAutomationBase
 from base import TestAutomationBase
 
 
-
[email protected]_main
[email protected]_periodic
 @pytest.mark.parametrize("launcher_platform", ['windows_editor'])
 @pytest.mark.parametrize("launcher_platform", ['windows_editor'])
 @pytest.mark.parametrize("project", ["AutomatedTesting"])
 @pytest.mark.parametrize("project", ["AutomatedTesting"])
 class TestAutomation(TestAutomationBase):
 class TestAutomation(TestAutomationBase):
-
-    def test_Opening_Closing_Pane(self, request, workspace, editor, launcher_platform):
-        from . import Opening_Closing_Pane as test_module
-        self._run_test(request, workspace, editor, test_module)
-
+    
     def test_Docking_Pane(self, request, workspace, editor, launcher_platform):
     def test_Docking_Pane(self, request, workspace, editor, launcher_platform):
         from . import Docking_Pane as test_module
         from . import Docking_Pane as test_module
         self._run_test(request, workspace, editor, test_module)
         self._run_test(request, workspace, editor, test_module)
@@ -36,4 +31,3 @@ class TestAutomation(TestAutomationBase):
     def test_Resizing_Pane(self, request, workspace, editor, launcher_platform):
     def test_Resizing_Pane(self, request, workspace, editor, launcher_platform):
         from . import Resizing_Pane as test_module
         from . import Resizing_Pane as test_module
         self._run_test(request, workspace, editor, test_module)
         self._run_test(request, workspace, editor, test_module)
-

+ 30 - 0
AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Sandbox.py

@@ -0,0 +1,30 @@
+"""
+All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+its licensors.
+
+For complete copyright and license terms please see the LICENSE at the root of this
+distribution (the "License"). All use of this software is governed by the License,
+or, if provided, by the license below or the license accompanying this file. Do not
+remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+"""
+
+import pytest
+import os
+import sys
+
+from ly_test_tools import LAUNCHERS
+
+sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesting_shared')
+
+from base import TestAutomationBase
+
+
[email protected]_sandbox
[email protected]("launcher_platform", ['windows_editor'])
[email protected]("project", ["AutomatedTesting"])
+class TestAutomation(TestAutomationBase):
+
+    def test_Opening_Closing_Pane(self, request, workspace, editor, launcher_platform):
+        from . import Opening_Closing_Pane as test_module
+        self._run_test(request, workspace, editor, test_module)

+ 36 - 6
AutomatedTesting/Registry/assets_scan_folders.setreg

@@ -3,15 +3,45 @@
     {
     {
         "Gems":
         "Gems":
         {
         {
-            "AutomatedTesting.Assets":
+            "DevTextures":
+            {
+                "SourcePaths":
+                [
+                    "Gems/DevTextures"
+                ]
+            },
+            "PBSreferenceMaterials":
+            {
+                "SourcePaths":
+                [
+                    "Gems/PBSreferenceMaterials"
+                ]
+            },
+            "PhysicsEntities":
+            {
+                "SourcePaths":
+                [
+                    "Gems/PhysicsEntities"
+                ]
+            },
+            "PhysXSamples":
+            {
+                "SourcePaths":
+                [
+                    "Gems/PhysXSamples"
+                ]
+            },
+            "PrimitiveAssets":
+            {
+                "SourcePaths":
+                [
+                    "Gems/PrimitiveAssets"
+                ]
+            },
+            "UiBasics":
             {
             {
                 "SourcePaths":
                 "SourcePaths":
                 [
                 [
-                    "Gems/DevTextures",
-                    "Gems/PBSreferenceMaterials",
-                    "Gems/PhysicsEntities",
-                    "Gems/PhysXSamples",
-                    "Gems/PrimitiveAssets",
                     "Gems/UiBasics"
                     "Gems/UiBasics"
                 ]
                 ]
             }
             }

+ 4 - 1
AutomatedTesting/TestAssets/test_chunks_builder.py

@@ -10,6 +10,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 """
 """
 import azlmbr.scene as sceneApi
 import azlmbr.scene as sceneApi
 from scene_api import scene_data as sceneData
 from scene_api import scene_data as sceneData
+import uuid
 
 
 def update_manifest(scene):
 def update_manifest(scene):
     graph = sceneData.SceneGraph(scene.graph)
     graph = sceneData.SceneGraph(scene.graph)
@@ -27,7 +28,9 @@ def update_manifest(scene):
     sceneManifest = sceneData.SceneManifest()
     sceneManifest = sceneData.SceneManifest()
 
 
     for activeMeshIndex in range(len(chunkNameList)):
     for activeMeshIndex in range(len(chunkNameList)):
-        meshGroup = sceneManifest.add_mesh_group(chunkNameList[activeMeshIndex])
+        chunkName = chunkNameList[activeMeshIndex]
+        meshGroup = sceneManifest.add_mesh_group(chunkName)
+        meshGroup['id'] = '{' + str(uuid.uuid5(uuid.NAMESPACE_DNS, scene.sourceFilename + chunkName)) + '}'
         sceneManifest.mesh_group_add_comment(meshGroup, 'auto generated by test_chunks_builder')
         sceneManifest.mesh_group_add_comment(meshGroup, 'auto generated by test_chunks_builder')
         sceneManifest.mesh_group_set_origin(meshGroup, None, 0, 0, 0, 1.0)
         sceneManifest.mesh_group_set_origin(meshGroup, None, 0, 0, 0, 1.0)
         for meshIndex in range(len(chunkNameList)):
         for meshIndex in range(len(chunkNameList)):

+ 1 - 1
AutomatedTesting/UI/TextureAtlas/sample.texatlas

@@ -1,2 +1,2 @@
-../Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/*map.tif
+@engroot@/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/*map.tif
 
 

+ 0 - 298
AutomatedTesting/gems.json

@@ -1,298 +0,0 @@
-{
-    "GemListFormatVersion": 2,
-    "Gems": [
-        {
-            "Path": "Gems/EMotionFX",
-            "Uuid": "044a63ea67d04479aa5daf62ded9d9ca",
-            "Version": "0.1.0",
-            "_comment": "EMotionFX"
-        },
-        {
-            "Path": "Gems/PBSreferenceMaterials",
-            "Uuid": "07375b61b1a2424bb03088bbdf28b2c8",
-            "Version": "0.1.0",
-            "_comment": "PBSreferenceMaterials"
-        },
-        {
-            "Path": "Gems/GraphModel",
-            "Uuid": "0844f64a3acf4f5abf3a535dc9b63bc9",
-            "Version": "0.1.0",
-            "_comment": "GraphModel"
-        },
-        {
-            "Path": "Gems/StartingPointInput",
-            "Uuid": "09f4bedeee614358bc36788e77f97e51",
-            "Version": "0.1.0",
-            "_comment": "StartingPointInput"
-        },
-        {
-            "Path": "Gems/LyShine",
-            "Uuid": "0fefab3f13364722b2eab3b96ce2bf20",
-            "Version": "0.1.0",
-            "_comment": "LyShine"
-        },
-        {
-            "Path": "Gems/LandscapeCanvas",
-            "Uuid": "19c2b2d5018940108baf252934b8e6bf",
-            "Version": "0.1.0",
-            "_comment": "LandscapeCanvas"
-        },
-        {
-            "Path": "Gems/ScriptCanvasPhysics",
-            "Uuid": "1c27519a4dda4ffaaeebf91514e5b1e8",
-            "Version": "0.1.0",
-            "_comment": "ScriptCanvasPhysics"
-        },
-        {
-            "Path": "Gems/HttpRequestor",
-            "Uuid": "28479e255bde466e91fc34eec808d9c7",
-            "Version": "1.0.0",
-            "_comment": "HttpRequestor"
-        },
-        {
-            "Path": "Gems/DevTextures",
-            "Uuid": "2c227161447b4d77a5b07c093e214fe3",
-            "Version": "0.1.0",
-            "_comment": "DevTextures"
-        },
-        {
-            "Path": "Gems/ScriptEvents",
-            "Uuid": "32d8ba21703e4bbbb08487366e48dd69",
-            "Version": "0.1.0",
-            "_comment": "ScriptEvents"
-        },
-        {
-            "Path": "Gems/Maestro",
-            "Uuid": "3b9a978ed6f742a1acb99f74379a342c",
-            "Version": "0.1.0",
-            "_comment": "Maestro"
-        },
-        {
-            "Path": "Gems/ExpressionEvaluation",
-            "Uuid": "4c6f9df57ca2468f93c8d860ee6a1167",
-            "Version": "0.1.0",
-            "_comment": "ExpressionEvaluation"
-        },
-        {
-            "Path": "Gems/PhysX",
-            "Uuid": "4e08125824434932a0fe3717259caa47",
-            "Version": "0.1.0",
-            "_comment": "PhysX"
-        },
-        {
-            "Path": "Gems/PhysXDebug",
-            "Uuid": "516145e2d9904b13813f1b54605e26a6",
-            "Version": "0.1.0",
-            "_comment": "PhysXDebug"
-        },
-        {
-            "Path": "Gems/CameraFramework",
-            "Uuid": "54f2763fe191432fa681ce4a354eedf5",
-            "Version": "0.1.0",
-            "_comment": "CameraFramework"
-        },
-        {
-            "Path": "Gems/TextureAtlas",
-            "Uuid": "5a149b6b3c964064bd4970f0e92f72e2",
-            "Version": "0.1.0",
-            "_comment": "TextureAtlas"
-        },
-        {
-            "Path": "Gems/SurfaceData",
-            "Uuid": "5de82d29d6094bfe97c1a4d35fcd5fbe",
-            "Version": "0.1.0",
-            "_comment": "SurfaceData"
-        },
-        {
-            "Path": "Gems/AssetValidation",
-            "Uuid": "5a5c3c10b91d4b4ea8baef474c5b5d49",
-            "Version": "0.1.0",
-            "_comment": "AssetValidation"
-        },
-        {
-            "Path": "Gems/Gestures",
-            "Uuid": "6056556b6088413984309c4a413593ad",
-            "Version": "1.0.0",
-            "_comment": "Gestures"
-        },
-        {
-            "Path": "Gems/CertificateManager",
-            "Uuid": "659cffff33b14a10835bafc6ea623f98",
-            "Version": "0.0.1",
-            "_comment": "CertificateManager"
-        },
-        {
-            "Path": "Gems/DebugDraw",
-            "Uuid": "66239f50bf754354b514c850c8b841fb",
-            "Version": "0.1.0",
-            "_comment": "DebugDraw"
-        },
-        {
-            "Path": "Gems/UiBasics",
-            "Uuid": "6bb61c9e547043f0afc5019d6d460b78",
-            "Version": "0.1.0",
-            "_comment": "UiBasics"
-        },
-        {
-            "Path": "Gems/AudioSystem",
-            "Uuid": "6f63f2b6d07f4b89b4b7c86ebee7feb8",
-            "Version": "0.1.0",
-            "_comment": "AudioSystem"
-        },
-        {
-            "Path": "Gems/StartingPointMovement",
-            "Uuid": "73d8779dc28a4123b7c9ed76217464af",
-            "Version": "0.1.0",
-            "_comment": "StartingPointMovement"
-        },
-        {
-            "Path": "Gems/GameLift",
-            "Uuid": "76de765796504906b73be7365a9bff06",
-            "Version": "2.0.0",
-            "_comment": "GameLift"
-        },
-        {
-            "Path": "Gems/SceneProcessing",
-            "Uuid": "7c2578f634df4345aca98d671e39b8ab",
-            "Version": "0.1.0",
-            "_comment": "SceneProcessing"
-        },
-        {
-            "Path": "Gems/StartingPointCamera",
-            "Uuid": "834070b9537d44df83559e2045c3859f",
-            "Version": "0.1.0",
-            "_comment": "StartingPointCamera"
-        },
-        {
-            "Path": "Gems/ScriptCanvas",
-            "Uuid": "869a0d0ec11a45c299917d45c81555e6",
-            "Version": "0.1.0",
-            "_comment": "ScriptCanvasGem"
-        },
-        {
-            "Path": "Gems/GraphCanvas",
-            "Uuid": "875b6fcbdeea44deaae7984ad9bb6cdc",
-            "Version": "0.1.0",
-            "_comment": "GraphCanvas"
-        },
-        {
-            "Path": "Gems/GradientSignal",
-            "Uuid": "8825563d9d964ec3be3bab681f3bd9f2",
-            "Version": "0.1.0",
-            "_comment": "GradientSignal"
-        },
-        {
-            "Path": "Gems/InAppPurchases",
-            "Uuid": "92fe57eae7d3402a90761973678c079a",
-            "Version": "0.1.0",
-            "_comment": "InAppPurchases"
-        },
-        {
-            "Path": "Gems/PhysicsEntities",
-            "Uuid": "99ea531451fc4f64a5a9fe8f385e8a76",
-            "Version": "0.1.0",
-            "_comment": "PhysicsEntities"
-        },
-        {
-            "Path": "AutomatedTesting/Gem",
-            "Uuid": "afc25e1593194d6283d9ff744ab6d5a1",
-            "Version": "0.1.0"
-        },
-        {
-            "Path": "Gems/EditorPythonBindings",
-            "Uuid": "b658359393884c4381c2fe2952b1472a",
-            "Version": "0.1.0",
-            "_comment": "EditorPythonBindings"
-        },
-        {
-            "Path": "Gems/ImGui",
-            "Uuid": "bab8807a1bc646b3909f3cc200ffeedf",
-            "Version": "0.1.0",
-            "_comment": "ImGui"
-        },
-        {
-            "Path": "Gems/ChatPlay",
-            "Uuid": "bfbc60c63ffd4b00927003735b26ce99",
-            "Version": "0.1.0",
-            "_comment": "ChatPlay"
-        },
-        {
-            "Path": "Gems/Metastream",
-            "Uuid": "c02d7efe05134983b5699d9ee7594c3a",
-            "Version": "1.0.0",
-            "_comment": "Metastream"
-        },
-        {
-            "Path": "Gems/PhysXSamples",
-            "Uuid": "c4a4aadba44241ae9f0141e145def7f7",
-            "Version": "0.1.0",
-            "_comment": "PhysXSamples"
-        },
-        {
-            "Path": "Gems/Water",
-            "Uuid": "c5083fcf89b24ab68fb0611c01a07b1d",
-            "Version": "0.1.0",
-            "_comment": "Water"
-        },
-        {
-            "Path": "Gems/WhiteBox",
-            "Uuid": "c5833dbda2e045d3a5f16b7414280c27",
-            "Version": "0.1.0",
-            "_comment": "WhiteBox"
-        },
-        {
-            "Path": "Gems/TouchBending",
-            "Uuid": "c58d2057f3724b22ae0df0be68a4e316",
-            "Version": "0.1.0",
-            "_comment": "TouchBending"
-        },
-        {
-            "Path": "Gems/FastNoise",
-            "Uuid": "c5f23032407f49ca8d8de1733423565c",
-            "Version": "0.1.0",
-            "_comment": "FastNoise"
-        },
-        {
-            "Path": "Gems/LyShineExamples",
-            "Uuid": "c7935ecf5e8047fe8ca947b34b11cadb",
-            "Version": "0.1.0",
-            "_comment": "LyShineExamples"
-        },
-        {
-            "Path": "Gems/PrimitiveAssets",
-            "Uuid": "ed07631f95fb4be1bd10cd37298ec697",
-            "Version": "1.0.0",
-            "_comment": "PrimitiveAssets"
-        },
-        {
-            "Path": "Gems/ImageProcessing",
-            "Uuid": "eeffbd9211cf4ce0b5cc73696b427cbe",
-            "Version": "0.1.0",
-            "_comment": "ImageProcessing"
-        },
-        {
-            "Path": "Gems/Vegetation",
-            "Uuid": "f394e7cf54424bba89615381bba9511b",
-            "Version": "0.1.0",
-            "_comment": "Vegetation"
-        },
-        {
-            "Path": "Gems/TestAssetBuilder",
-            "Uuid": "f5c92f1560714010ba30467d93feecef",
-            "Version": "0.1.0",
-            "_comment": "TestAssetBuilder"
-        },
-        {
-            "Path": "Gems/Camera",
-            "Uuid": "f910686b6725452fbfc4671f95f733c6",
-            "Version": "0.1.0",
-            "_comment": "Camera"
-        },
-        {
-            "Path": "Gems/LmbrCentral",
-            "Uuid": "ff06785f7145416b9d46fde39098cb0c",
-            "Version": "0.1.0",
-            "_comment": "LmbrCentral"
-        }
-    ]
-}

+ 2 - 2
BuildReleaseAuxiliaryContent.py

@@ -24,12 +24,12 @@ def printMessage(message):
 def getCurrentProject():
 def getCurrentProject():
     bootstrap = open("bootstrap.cfg", "r")
     bootstrap = open("bootstrap.cfg", "r")
 
 
-    gameProjectRegex = re.compile("^sys_game_folder\s*=\s*(.*)")
+    gameProjectRegex = re.compile(r"^project_path\s*=\s*(.*)")
 
 
     for line in bootstrap:
     for line in bootstrap:
         gameFolderMatch = gameProjectRegex.match(line)
         gameFolderMatch = gameProjectRegex.match(line)
         if gameFolderMatch:
         if gameFolderMatch:
-            return gameFolderMatch.group(1)
+            return os.path.basename(gameFolderMatch.group(1))
     return None
     return None
 
 
 
 

+ 22 - 5
CMakeLists.txt

@@ -24,7 +24,7 @@ endif()
 include(cmake/Version.cmake)
 include(cmake/Version.cmake)
 
 
 if(NOT PROJECT_NAME)
 if(NOT PROJECT_NAME)
-    project(Lumberyard 
+    project(O3DE
         LANGUAGES C CXX
         LANGUAGES C CXX
         VERSION ${LY_VERSION_STRING}
         VERSION ${LY_VERSION_STRING}
     )
     )
@@ -83,13 +83,30 @@ endif()
 # Post-processing
 # Post-processing
 ################################################################################
 ################################################################################
 
 
+# Loop over the additional external subdirectories and invoke add_subdirectory on them
+foreach(external_directory ${LY_EXTERNAL_SUBDIRS})
+    # Hash the extenal_directory name and append it to the Binary Directory section of add_subdirectory
+    # This is to deal with potential situations where multiple external directories has the same last directory name
+    # For example if D:/Company1/RayTracingGem and F:/Company2/Path/RayTracingGem were both added as a subdirectory
+    file(REAL_PATH ${external_directory} full_directory_path)
+    string(SHA256 full_directory_hash ${full_directory_path})
+    # Truncate the full_directory_hash down to 8 characters to avoid hitting the Windows 260 character path limit
+    # when the external subdirectory contains relative paths of significant length
+    string(SUBSTRING ${full_directory_hash} 0 8 full_directory_hash)
+    # Use the last directory as the suffix path to use for the Binary Directory
+    get_filename_component(directory_name ${external_directory} NAME)
+    add_subdirectory(${external_directory} ${CMAKE_BINARY_DIR}/${directory_name}-${full_directory_hash})
+endforeach()
+
 # The following steps have to be done after all targets were registered:
 # The following steps have to be done after all targets were registered:
-# 1. link targets where the dependency was yet not declared, we need to have the declaration so we do different
-#    linking logic depending on the type of target
-ly_delayed_target_link_libraries()
-# 2. generate a settings registry .setreg file for all ly_add_project_dependencies() and ly_add_target_dependencies() calls
+# 1. generate a settings registry .setreg file for all ly_add_project_dependencies() and ly_add_target_dependencies() calls
 #    to provide applications with the filenames of gem modules to load
 #    to provide applications with the filenames of gem modules to load
+#    This must be done before ly_delayed_target_link_libraries() as that inserts BUILD_DEPENDENCIE as MANUALLY_ADDED_DEPENDENCIES
+#    if the build dependency is a MODULE_LIBRARY. That would cause a false load dependency to be generated
 ly_delayed_generate_settings_registry()
 ly_delayed_generate_settings_registry()
+# 2. link targets where the dependency was yet not declared, we need to have the declaration so we do different
+#    linking logic depending on the type of target
+ly_delayed_target_link_libraries()
 # 3. generate a registry file for unit testing for platforms that support unit testing
 # 3. generate a registry file for unit testing for platforms that support unit testing
 if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
 if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
     ly_delayed_generate_unit_test_module_registry()
     ly_delayed_generate_unit_test_module_registry()

+ 1 - 1
Code/CryEngine/Cry3DEngine/3DEngineRender.cpp

@@ -1080,7 +1080,7 @@ void C3DEngine::WorldStreamUpdate()
 
 
                 if (GetCVars()->e_StreamSaveStartupResultsIntoXML)
                 if (GetCVars()->e_StreamSaveStartupResultsIntoXML)
                 {
                 {
-                    const char* testResultsFile = "@cache@/TestResults/Streaming_Level_Start_Throughput.xml";
+                    const char* testResultsFile = "@usercache@/TestResults/Streaming_Level_Start_Throughput.xml";
 
 
                     AZ::IO::HandleType resultsFile = gEnv->pCryPak->FOpen(testResultsFile, "wb");
                     AZ::IO::HandleType resultsFile = gEnv->pCryPak->FOpen(testResultsFile, "wb");
                     if (resultsFile != AZ::IO::InvalidHandle)
                     if (resultsFile != AZ::IO::InvalidHandle)

+ 1 - 1
Code/CryEngine/Cry3DEngine/3dEngine.cpp

@@ -952,7 +952,7 @@ void C3DEngine::ProcessStreamingLatencyTest(const CCamera& camIn, CCamera& camOu
 
 
                 if (GetCVars()->e_SQTestCount == 0)
                 if (GetCVars()->e_SQTestCount == 0)
                 {
                 {
-                    const char* testResultsFile = "@cache@/TestResults/Streaming_Latency_Test.xml";
+                    const char* testResultsFile = "@usercache@/TestResults/Streaming_Latency_Test.xml";
 
 
                     AZ::IO::HandleType resultsFile = gEnv->pCryPak->FOpen(testResultsFile, "wb");
                     AZ::IO::HandleType resultsFile = gEnv->pCryPak->FOpen(testResultsFile, "wb");
                     if (resultsFile != AZ::IO::InvalidHandle)
                     if (resultsFile != AZ::IO::InvalidHandle)

+ 2 - 12
Code/CryEngine/Cry3DEngine/3dEngineLoad.cpp

@@ -461,7 +461,7 @@ void C3DEngine::UnloadLevel()
     m_ptexIconLowMemoryUsage = nullptr;
     m_ptexIconLowMemoryUsage = nullptr;
     m_ptexIconHighMemoryUsage = nullptr;
     m_ptexIconHighMemoryUsage = nullptr;
     m_ptexIconEditorConnectedToConsole = nullptr;
     m_ptexIconEditorConnectedToConsole = nullptr;
-    
+
     if (m_pOpticsManager && !gEnv->IsEditor())
     if (m_pOpticsManager && !gEnv->IsEditor())
     {
     {
         m_pOpticsManager->Reset();
         m_pOpticsManager->Reset();
@@ -656,7 +656,7 @@ bool C3DEngine::LoadLevel(const char* szFolderName, const char* szMissionName)
         // set default render parameters.
         // set default render parameters.
         // for some reason this is not done later???
         // for some reason this is not done later???
         m_pSkyLightManager->UpdateRenderParams();
         m_pSkyLightManager->UpdateRenderParams();
-    }    
+    }
 
 
     // Load LevelData.xml File.
     // Load LevelData.xml File.
     XmlNodeRef xmlLevelData = GetSystem()->LoadXmlFromFile(GetLevelFilePath(LEVEL_DATA_FILE));
     XmlNodeRef xmlLevelData = GetSystem()->LoadXmlFromFile(GetLevelFilePath(LEVEL_DATA_FILE));
@@ -687,17 +687,7 @@ bool C3DEngine::LoadLevel(const char* szFolderName, const char* szMissionName)
     // preload level cgfs
     // preload level cgfs
     if (GetCVars()->e_StatObjPreload && !gEnv->IsEditor())
     if (GetCVars()->e_StatObjPreload && !gEnv->IsEditor())
     {
     {
-        if (GetCVars()->e_StatObjPreload == 2)
-        {
-            GetSystem()->OutputLoadingTimeStats();
-        }
-
         m_pObjManager->PreloadLevelObjects();
         m_pObjManager->PreloadLevelObjects();
-
-        if (GetCVars()->e_StatObjPreload == 2)
-        {
-            GetSystem()->OutputLoadingTimeStats();
-        }
     }
     }
 
 
     std::vector<struct IStatObj*>* pStatObjTable = NULL;
     std::vector<struct IStatObj*>* pStatObjTable = NULL;

+ 2 - 1
Code/CryEngine/Cry3DEngine/LightEntity.cpp

@@ -317,7 +317,8 @@ int CLightEntity::UpdateGSMLightSourceDynamicShadowFrustum(int nDynamicLodCount,
 
 
         if (bDoGSM)
         if (bDoGSM)
         {
         {
-            Vec3 vSunDir = Get3DEngine()->GetSunDir().GetNormalized();  // todo: remove GetNormalized() once GetSunDir() returns the normalized value
+            //Vec3 vSunDir = Get3DEngine()->GetSunDir().GetNormalized();  // todo: remove GetNormalized() once GetSunDir() returns the normalized value
+            Vec3 vSunDir = Vec3(1.0f, 0.0f, 0.0f);
             Vec3 vCameraDirWithoutDepth = vCameraDir - vCameraDir.Dot(vSunDir) * vSunDir;
             Vec3 vCameraDirWithoutDepth = vCameraDir - vCameraDir.Dot(vSunDir) * vSunDir;
 
 
             Vec3 vFocusPos = passInfo.GetCamera().GetPosition() + vCameraDirWithoutDepth * fGSMBoxSize;
             Vec3 vFocusPos = passInfo.GetCamera().GetPosition() + vCameraDirWithoutDepth * fGSMBoxSize;

+ 1 - 14
Code/CryEngine/Cry3DEngine/Material.cpp

@@ -117,10 +117,6 @@ CMatInfo::CMatInfo()
 
 
     ZeroStruct(m_streamZoneInfo);
     ZeroStruct(m_streamZoneInfo);
 
 
-#ifdef TRACE_MATERIAL_LEAKS
-    m_sLoadingCallstack = GetSystem()->GetLoadingProfilerCallstack();
-#endif
-
     // Used to know when a .dccmtl file has been changed,
     // Used to know when a .dccmtl file has been changed,
     // requiring the source material to be updated
     // requiring the source material to be updated
     m_dccMaterialHash = 0;
     m_dccMaterialHash = 0;
@@ -341,7 +337,7 @@ ISurfaceType* CMatInfo::GetSurfaceType()
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 void CMatInfo::SetSubMtlCount(int numSubMtl)
 void CMatInfo::SetSubMtlCount(int numSubMtl)
 {
 {
-    AUTO_LOCK(GetSubMaterialResizeLock());    
+    AUTO_LOCK(GetSubMaterialResizeLock());
     if (numSubMtl > 0)
     if (numSubMtl > 0)
     {
     {
         m_Flags |= MTL_FLAG_MULTI_SUBMTL;
         m_Flags |= MTL_FLAG_MULTI_SUBMTL;
@@ -1112,15 +1108,6 @@ void CMatInfo::SetTexelDensityDebug([[maybe_unused]] int mode)
 #endif
 #endif
 }
 }
 
 
-const char* CMatInfo::GetLoadingCallstack()
-{
-#ifdef TRACE_MATERIAL_LEAKS
-    return m_sLoadingCallstack.c_str();
-#else
-    return "";
-#endif
-}
-
 void CMatInfo::PrecacheMaterial(const float _fEntDistance, IRenderMesh* pRenderMesh, bool bFullUpdate, bool bDrawNear)
 void CMatInfo::PrecacheMaterial(const float _fEntDistance, IRenderMesh* pRenderMesh, bool bFullUpdate, bool bDrawNear)
 {
 {
     //  FUNCTION_PROFILER_3DENGINE;
     //  FUNCTION_PROFILER_3DENGINE;

+ 1 - 14
Code/CryEngine/Cry3DEngine/Material.h

@@ -18,7 +18,6 @@
 #include <IMaterial.h>
 #include <IMaterial.h>
 
 
 #if !defined(CONSOLE)
 #if !defined(CONSOLE)
-#   define TRACE_MATERIAL_LEAKS
 #   define SUPPORT_MATERIAL_EDITING
 #   define SUPPORT_MATERIAL_EDITING
 #endif
 #endif
 
 
@@ -203,7 +202,7 @@ public:
     bool SetGetMaterialParamFloat(const char* sParamName, float& v, bool bGet, bool allowShaderParam = false, int materialIndex = 0) override;
     bool SetGetMaterialParamFloat(const char* sParamName, float& v, bool bGet, bool allowShaderParam = false, int materialIndex = 0) override;
     bool SetGetMaterialParamVec3(const char* sParamName, Vec3& v, bool bGet, bool allowShaderParam = false, int materialIndex = 0) override;
     bool SetGetMaterialParamVec3(const char* sParamName, Vec3& v, bool bGet, bool allowShaderParam = false, int materialIndex = 0) override;
     bool SetGetMaterialParamVec4(const char* sParamName, Vec4& v, bool bGet, bool allowShaderParam = false, int materialIndex = 0) override;
     bool SetGetMaterialParamVec4(const char* sParamName, Vec4& v, bool bGet, bool allowShaderParam = false, int materialIndex = 0) override;
-    
+
     void SetDirty(bool dirty = true) override;
     void SetDirty(bool dirty = true) override;
     bool IsDirty() const override;
     bool IsDirty() const override;
 
 
@@ -264,11 +263,6 @@ public:
     bool IsForwardRenderingRequired();
     bool IsForwardRenderingRequired();
     bool IsNearestCubemapRequired();
     bool IsNearestCubemapRequired();
 
 
-    //////////////////////////////////////////////////////////////////////////
-    // Debug routines
-    //////////////////////////////////////////////////////////////////////////
-    virtual const char* GetLoadingCallstack();  // trace leaking materials by callstack
-
     void DisableTextureStreaming() override;
     void DisableTextureStreaming() override;
     virtual void RequestTexturesLoading(const float fMipFactor);
     virtual void RequestTexturesLoading(const float fMipFactor);
 
 
@@ -286,13 +280,6 @@ public:
     void SetDccMaterialHash(uint32 hash) override { m_dccMaterialHash = hash; }
     void SetDccMaterialHash(uint32 hash) override { m_dccMaterialHash = hash; }
 
 
     virtual CryCriticalSection& GetSubMaterialResizeLock();
     virtual CryCriticalSection& GetSubMaterialResizeLock();
-public:
-    //////////////////////////////////////////////////////////////////////////
-    // for debug purposes
-    //////////////////////////////////////////////////////////////////////////
-#ifdef TRACE_MATERIAL_LEAKS
-    string  m_sLoadingCallstack;
-#endif
 
 
 private:
 private:
     friend class CMatMan;
     friend class CMatMan;

+ 1 - 9
Code/CryEngine/Cry3DEngine/StatObj.h

@@ -16,7 +16,6 @@
 #pragma once
 #pragma once
 
 
 #if !defined(CONSOLE)
 #if !defined(CONSOLE)
-#   define TRACE_CGF_LEAKS
 #   define SUPPORT_TERRAIN_AO_PRE_COMPUTATIONS
 #   define SUPPORT_TERRAIN_AO_PRE_COMPUTATIONS
 #endif
 #endif
 
 
@@ -337,13 +336,6 @@ public:
     std::vector<uint16> m_chunkBoneIds;
     std::vector<uint16> m_chunkBoneIds;
     //////////////////////////////////////////////////////////////////////////
     //////////////////////////////////////////////////////////////////////////
 
 
-    //////////////////////////////////////////////////////////////////////////
-    // for debug purposes
-    //////////////////////////////////////////////////////////////////////////
-#ifdef TRACE_CGF_LEAKS
-    string  m_sLoadingCallstack;
-#endif
-
 private:
 private:
     //////////////////////////////////////////////////////////////////////////
     //////////////////////////////////////////////////////////////////////////
     // Sub objects.
     // Sub objects.
@@ -419,7 +411,7 @@ public:
     virtual unsigned int GetBreakableByGame() { return m_bBreakableByGame; };
     virtual unsigned int GetBreakableByGame() { return m_bBreakableByGame; };
 
 
     //Note: This function checks both the children and root data
     //Note: This function checks both the children and root data
-    //It should really be 'has any deformable objects' 
+    //It should really be 'has any deformable objects'
     //Should eventually be refactored as part of an eventual statobj refactor.
     //Should eventually be refactored as part of an eventual statobj refactor.
     virtual bool IsDeformable() override;
     virtual bool IsDeformable() override;
 
 

+ 0 - 4
Code/CryEngine/Cry3DEngine/StatObjConstr.cpp

@@ -56,10 +56,6 @@ CStatObj::CStatObj()
     m_fLodDistance = 0.0f;
     m_fLodDistance = 0.0f;
 
 
     Init();
     Init();
-
-#ifdef TRACE_CGF_LEAKS
-    m_sLoadingCallstack = GetSystem()->GetLoadingProfilerCallstack();
-#endif
 }
 }
 
 
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////

+ 1 - 1
Code/CryEngine/CryCommon/IAudioSystem.h

@@ -1064,7 +1064,7 @@ namespace Audio
             ///////////////////////////////////////////////////////////////////////////////////////////
             ///////////////////////////////////////////////////////////////////////////////////////////
 
 
             // Interface methods
             // Interface methods
-            virtual bool Initialize(const SSystemInitParams* initParams) = 0;
+            virtual bool Initialize() = 0;
             virtual void Release() = 0;
             virtual void Release() = 0;
         };
         };
 
 

+ 1 - 6
Code/CryEngine/CryCommon/IMaterial.h

@@ -392,7 +392,7 @@ struct IMaterial
     virtual void SetDirty(bool dirty = true) = 0;
     virtual void SetDirty(bool dirty = true) = 0;
     virtual bool IsDirty() const = 0;
     virtual bool IsDirty() const = 0;
 
 
-    //! Returns true if the material is the parent of a group of materials 
+    //! Returns true if the material is the parent of a group of materials
     virtual bool IsMaterialGroup() const = 0;
     virtual bool IsMaterialGroup() const = 0;
 
 
     //! Returns true if the material is a single material belongs to a material group
     //! Returns true if the material is a single material belongs to a material group
@@ -411,11 +411,6 @@ struct IMaterial
     //  - 2, fast sketch mode.
     //  - 2, fast sketch mode.
     virtual void SetSketchMode(int mode) = 0;
     virtual void SetSketchMode(int mode) = 0;
 
 
-    //////////////////////////////////////////////////////////////////////////
-    // Debug routines
-    //////////////////////////////////////////////////////////////////////////
-    virtual const char* GetLoadingCallstack() = 0;  // trace leaking materials by callstack
-
     // Sets FT_DONT_STREAM flag for all textures used by the material
     // Sets FT_DONT_STREAM flag for all textures used by the material
     // If a stream is already in process, this will stop the stream and flush the device texture
     // If a stream is already in process, this will stop the stream and flush the device texture
     virtual void DisableTextureStreaming() = 0;
     virtual void DisableTextureStreaming() = 0;

+ 7 - 189
Code/CryEngine/CryCommon/ISystem.h

@@ -119,8 +119,6 @@ namespace AZ
 
 
 class IResourceCompilerHelper;
 class IResourceCompilerHelper;
 
 
-class CBootProfilerRecord;
-
 namespace Serialization {
 namespace Serialization {
     struct IArchiveHost;
     struct IArchiveHost;
 }
 }
@@ -629,15 +627,7 @@ struct SSystemInitParams
     void* hWnd;                                     //
     void* hWnd;                                     //
     void* hWndForInputSystem;                       // the HWND for the input devices, distinct from the hWnd, which the rendering system overrides anyways
     void* hWndForInputSystem;                       // the HWND for the input devices, distinct from the hWnd, which the rendering system overrides anyways
 
 
-    char remoteIP[256];
-    int  remotePort;
-    bool remoteFileIO;
     bool remoteResourceCompiler;
     bool remoteResourceCompiler;
-    bool connectToRemote;
-    bool waitForConnection; // if true, wait for the remote connection to be established before proceeding to system init.
-    char assetsPlatform[64]; // what flavor of assets to load.  Corresponds to those in rc.ini and asset processor ini
-    char gameFolderName[256]; // just the name.  Not the full path.
-    char branchToken[12]; // information written by the assetprocessor which help determine whether the game/editor are running from the same branch or not
 
 
     ILog* pLog;                                     // You can specify your own ILog to be used by System.
     ILog* pLog;                                     // You can specify your own ILog to be used by System.
     ILogCallback* pLogCallback;                     // You can specify your own ILogCallback to be added on log creation (used by Editor).
     ILogCallback* pLogCallback;                     // You can specify your own ILogCallback to be added on log creation (used by Editor).
@@ -648,45 +638,6 @@ struct SSystemInitParams
     IOutputPrintSink* pPrintSync;               // Print Sync which can be used to catch all output from engine
     IOutputPrintSink* pPrintSync;               // Print Sync which can be used to catch all output from engine
     char szSystemCmdLine[2048];                     // Command line.
     char szSystemCmdLine[2048];                     // Command line.
 
 
-
-                                                    // set some paths before you create the system.
-
-                                                    // rootPath - (REQUIRED) folder containing root.  Must contain system.cfg or bootstrap.cfg basically.
-                                                    // the remainder are optional and if specified should contain prefixes that can be prepended to any file to get to that location:
-                                                    // READ ONLY!
-    char rootPath[256];
-    char rootPathCache[256];
-
-    // assetsPath - (REQUIRED) - where you assets live.  The engine config parser will default this to @root@/gamename
-    // READ ONLY!
-    char assetsPath[256];
-    char assetsPathCache[256];
-
-    // userPath - (OPTIONAL) User path contains a folder for preferences persistent storage.  May be persisted to the cloud (by things like IOS)
-    // If not specified, this is assumed @root@/User/
-    // WRITABLE
-    char userPath[256];
-
-    // cachePath - (OPTIONAL) a temporary store that can be erased at any time and does not need to be persisted
-    // on the cloud or anything like that. if not specified, this will be @user@/Cache
-    // WRITABLE
-    char cachePath[256];
-
-    // logPath - (OPTIONAL) a log path folder.
-    // If not specified, it will be @cache@/Logs
-    // WRITABLE
-    char logPath[256];
-
-    // the game should never use these values instead, the game should be using crypak or fileio with aliases:
-    // @root@ To get to the folder where system.cfg lives
-    // @assets@ to get to the folder containing game assets (textures and such) - by default, this is @root@/Gamename/
-    // @devroot@ to get to source files that are checked into source control (PC EDITOR ONLY!)
-    // @engroot@ to get to path to the engine root folder
-    // @user@ to access user store
-    // @cache@ to access temporary cache
-    // @log@ to access log file and other forensic storage
-    char szBinariesDir[256];
-
     bool bEditor;                                   // When running in Editor mode.
     bool bEditor;                                   // When running in Editor mode.
     bool bPreview;                                  // When running in Preview mode (Minimal initialization).
     bool bPreview;                                  // When running in Preview mode (Minimal initialization).
     bool bTestMode;                                 // When running in Automated testing mode.
     bool bTestMode;                                 // When running in Automated testing mode.
@@ -730,26 +681,7 @@ struct SSystemInitParams
         hWnd = NULL;
         hWnd = NULL;
         hWndForInputSystem = NULL;
         hWndForInputSystem = NULL;
 
 
-        memset(rootPath, 0, sizeof(rootPath));
-        memset(rootPathCache, 0, sizeof(rootPathCache));
-        memset(userPath, 0, sizeof(userPath));
-        memset(assetsPath, 0, sizeof(assetsPath));
-        memset(assetsPathCache, 0, sizeof(assetsPathCache));
-        memset(cachePath, 0, sizeof(cachePath));
-        memset(logPath, 0, sizeof(logPath));
-        memset(gameFolderName, 0, sizeof(gameFolderName));
-        memset(branchToken, 0, sizeof(branchToken));
-
-        memset(remoteIP, 0, sizeof(remoteIP));
-        azstrcpy(remoteIP, sizeof(remoteIP), "127.0.0.1");
-        memset(assetsPlatform, 0, sizeof(assetsPlatform));
-        azstrcpy(assetsPlatform, sizeof(assetsPlatform), "pc");
-
-        remotePort = 45643;
-        remoteFileIO = false;
         remoteResourceCompiler = false;
         remoteResourceCompiler = false;
-        connectToRemote = false;
-        waitForConnection = false;
 
 
         pLog = NULL;
         pLog = NULL;
         pLogCallback = NULL;
         pLogCallback = NULL;
@@ -762,7 +694,6 @@ struct SSystemInitParams
         pValidator = NULL;
         pValidator = NULL;
         pPrintSync = NULL;
         pPrintSync = NULL;
         memset(szSystemCmdLine, 0, sizeof(szSystemCmdLine));
         memset(szSystemCmdLine, 0, sizeof(szSystemCmdLine));
-        memset(szBinariesDir, 0, sizeof(szBinariesDir));
 
 
         bEditor = false;
         bEditor = false;
         bPreview = false;
         bPreview = false;
@@ -798,17 +729,6 @@ struct SSystemInitParams
 
 
         pSharedEnvironment = nullptr;
         pSharedEnvironment = nullptr;
     }
     }
-
-    bool UseAssetCache() const
-    {
-#if defined(AZ_PLATFORM_WINDOWS) || defined(AZ_PLATFORM_MAC) || defined(AZ_PLATFORM_LINUX)
-        char checkPath[AZ_MAX_PATH_LEN] = { 0 };
-        azsnprintf(checkPath, AZ_MAX_PATH_LEN, "%s/engine.json", rootPathCache);
-        return AZ::IO::SystemFile::Exists(checkPath);
-#else
-        return false;
-#endif // defined(AZ_PLATFORM_WINDOWS) || AZ_TRAIT_OS_PLATFORM_APPLE
-    }
 };
 };
 
 
 // Notes:
 // Notes:
@@ -1228,11 +1148,6 @@ struct ISystem
     //   Gets number of CPUs
     //   Gets number of CPUs
     virtual int GetLogicalCPUCount() = 0;
     virtual int GetLogicalCPUCount() = 0;
 
 
-    //! Get the 'kind' of assets you need to load - this describes the flavor of assets you are going to load
-    //! based on the platform you're on - so for example, android on ES3 will be 'es3' but android on opengl might load PC assets or others...
-    //! This is defined in bootstrap.cfg and is read-only during runtime.
-    virtual const char* GetAssetsPlatform() const = 0;
-
     // Summary:
     // Summary:
     //   Return the rendering driver name. GL or Metal
     //   Return the rendering driver name. GL or Metal
     virtual const char* GetRenderingDriverName() const = 0;
     virtual const char* GetRenderingDriverName() const = 0;
@@ -1406,43 +1321,6 @@ struct ISystem
     //   True if system running in Test mode.
     //   True if system running in Test mode.
     virtual bool IsTestMode() const = 0;
     virtual bool IsTestMode() const = 0;
 
 
-    //////////////////////////////////////////////////////////////////////////
-    // Loading time/memory profiling
-    //////////////////////////////////////////////////////////////////////////
-
-    // Summary:
-    //   Starts function loading stats profiling.
-    virtual struct SLoadingTimeContainer* StartLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler, const char* szFuncName) = 0;
-
-    // Summary:
-    //   Ends function loading stats profiling.
-    virtual void EndLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler) = 0;
-
-    // Summary:
-    //   Starts function profiling with bootprofiler (session must be started).
-    virtual CBootProfilerRecord* StartBootSectionProfiler(const char* name, const char* args) = 0;
-
-    // Summary:
-    //   Ends function profiling with bootprofiler.
-    virtual void StopBootSectionProfiler(CBootProfilerRecord* record) = 0;
-
-
-    // Summary:
-    //   Starts frame session
-    virtual void StartBootProfilerSessionFrames(const char* pName) = 0;
-
-    // Summary:
-    //   Stops frame session
-    virtual void StopBootProfilerSessionFrames() = 0;
-
-    // Summary:
-    //   Prints loading stats into log.
-    virtual void OutputLoadingTimeStats() = 0;
-
-    // Summary:
-    //   Starts function loading stats profiling.
-    virtual const char* GetLoadingProfilerCallstack() = 0;
-
     //////////////////////////////////////////////////////////////////////////
     //////////////////////////////////////////////////////////////////////////
     // File version.
     // File version.
     //////////////////////////////////////////////////////////////////////////
     //////////////////////////////////////////////////////////////////////////
@@ -1581,10 +1459,10 @@ struct ISystem
     //////////////////////////////////////////////////////////////////////////
     //////////////////////////////////////////////////////////////////////////
 
 
     // Summary:
     // Summary:
-    //  Enable/Disable drawing the console 
+    //  Enable/Disable drawing the console
     virtual void SetConsoleDrawEnabled(bool enabled) = 0;
     virtual void SetConsoleDrawEnabled(bool enabled) = 0;
 
 
-    //  Enable/Disable drawing the UI 
+    //  Enable/Disable drawing the UI
     virtual void SetUIDrawEnabled(bool enabled) = 0;
     virtual void SetUIDrawEnabled(bool enabled) = 0;
 
 
     // Summary:
     // Summary:
@@ -1772,79 +1650,19 @@ struct DiskOperationInfo
 
 
 #endif
 #endif
 
 
-#if defined(ENABLE_LOADING_PROFILER)
-
-struct CLoadingTimeProfiler
-{
-    CLoadingTimeProfiler(ISystem* pSystem, const char* szFuncName)
-        : m_pSystem(pSystem)
-    {
-        m_pSystem = pSystem;
-        m_pTimeContainer = m_pSystem->StartLoadingSectionProfiling(this, szFuncName);
-    }
-
-    ~CLoadingTimeProfiler()
-    {
-        m_pSystem->EndLoadingSectionProfiling(this);
-    }
-
-    struct SLoadingTimeContainer* m_pTimeContainer;
-    double m_fConstructorTime;
-    double m_fConstructorMemUsage;
-
-    DiskOperationInfo m_constructorInfo;
-
-    ISystem* m_pSystem;
-};
-
-class CSYSBootProfileBlock
-{
-    ISystem* m_pSystem;
-    CBootProfilerRecord* m_pRecord;
-public:
-    CSYSBootProfileBlock(ISystem* pSystem, const char* name, const char* args = NULL)
-        : m_pSystem(pSystem)
-    {
-        if (m_pSystem)
-        {
-            m_pRecord = m_pSystem->StartBootSectionProfiler(name, args);
-        }
-    }
-
-    ~CSYSBootProfileBlock()
-    {
-        if (m_pSystem)
-        {
-            m_pSystem->StopBootSectionProfiler(m_pRecord);
-        }
-    }
-};
-
-#ifdef AZ_PROFILE_TELEMETRY
+#if defined(ENABLE_LOADING_PROFILER) && AZ_PROFILE_TELEMETRY
 
 
 #define LOADING_TIME_PROFILE_SECTION AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzCore)
 #define LOADING_TIME_PROFILE_SECTION AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzCore)
 #define LOADING_TIME_PROFILE_SECTION_ARGS(...) AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, __VA_ARGS__)
 #define LOADING_TIME_PROFILE_SECTION_ARGS(...) AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, __VA_ARGS__)
 #define LOADING_TIME_PROFILE_SECTION_NAMED(sectionName) AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzCore, sectionName)
 #define LOADING_TIME_PROFILE_SECTION_NAMED(sectionName) AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzCore, sectionName)
-#define LOADING_TIME_PROFILE_SECTION_NAMED_ARGS(sectionName, args) AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, sectionName, args)
-
-#else
-
-#define LOADING_TIME_PROFILE_SECTION CSYSBootProfileBlock AZ_JOIN(_profileBlockLine, __LINE__)(gEnv && gEnv->pSystem ? gEnv->pSystem : nullptr, __FUNCTION__);
-#define LOADING_TIME_PROFILE_SECTION_ARGS(args) CSYSBootProfileBlock AZ_JOIN(_profileBlockLine, __LINE__)(gEnv->pSystem, __FUNCTION__, args);
-#define LOADING_TIME_PROFILE_SECTION_NAMED(sectionName) CSYSBootProfileBlock AZ_JOIN(_profileBlockLine, __LINE__)(gEnv->pSystem, sectionName);
-#define LOADING_TIME_PROFILE_SECTION_NAMED_ARGS(sectionName, args) CSYSBootProfileBlock AZ_JOIN(_profileBlockLine, __LINE__)(gEnv->pSystem, sectionName, args);
-
-#endif // AZ_PROFILE_TELEMETRY
+#define LOADING_TIME_PROFILE_SECTION_NAMED_ARGS(sectionName, ...) AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, sectionName, __VA_ARGS__)
 
 
 #else
 #else
 
 
 #define LOADING_TIME_PROFILE_SECTION
 #define LOADING_TIME_PROFILE_SECTION
-#define LOADING_TIME_PROFILE_SECTION_ARGS(args)
+#define LOADING_TIME_PROFILE_SECTION_ARGS(...)
 #define LOADING_TIME_PROFILE_SECTION_NAMED(sectionName)
 #define LOADING_TIME_PROFILE_SECTION_NAMED(sectionName)
-#define LOADING_TIME_PROFILE_SECTION_NAMED_ARGS(sectionName, args)
-#define LOADING_TIME_PROFILE_SESSION_SECTION(sessionName)
-#define LOADING_TIME_PROFILE_SESSION_START(sessionName)
-#define LOADING_TIME_PROFILE_SESSION_STOP(sessionName)
+#define LOADING_TIME_PROFILE_SECTION_NAMED_ARGS(sectionName, ...)
 
 
 #endif
 #endif
 
 
@@ -1865,7 +1683,7 @@ extern SC_API SSystemGlobalEnvironment* gEnv;
 inline ISystem* GetISystem()
 inline ISystem* GetISystem()
 {
 {
     // Some unit tests temporarily install and then uninstall ISystem* mocks.
     // Some unit tests temporarily install and then uninstall ISystem* mocks.
-    // It is generally okay for runtime and tool systems which call this function to cache the returned pointer, 
+    // It is generally okay for runtime and tool systems which call this function to cache the returned pointer,
     // because their lifetime is usually shorter than the lifetime of the ISystem* implementation.
     // because their lifetime is usually shorter than the lifetime of the ISystem* implementation.
     // It is NOT safe for this function to cache it as a static itself, though, as the static it would cache
     // It is NOT safe for this function to cache it as a static itself, though, as the static it would cache
     // it inside may outlive the the actual instance implementing ISystem* when unit tests are torn down and then restarted.
     // it inside may outlive the the actual instance implementing ISystem* when unit tests are torn down and then restarted.

+ 7 - 8
Code/CryEngine/CryCommon/MaterialUtils.h

@@ -15,10 +15,12 @@
 
 
 #include <AzCore/base.h>
 #include <AzCore/base.h>
 #include <AzCore/IO/SystemFile.h> // for max path len
 #include <AzCore/IO/SystemFile.h> // for max path len
-#include <ISystem.h>
 #include <AzCore/std/string/string.h>
 #include <AzCore/std/string/string.h>
+#include <AzCore/Utils/Utils.h>
 #include <AzFramework/StringFunc/StringFunc.h>
 #include <AzFramework/StringFunc/StringFunc.h>
 
 
+#include <ISystem.h>
+
 namespace MaterialUtils
 namespace MaterialUtils
 {
 {
     //! UnifyMaterialName - given a non-unified material name, remove the extension, unify the slashes
     //! UnifyMaterialName - given a non-unified material name, remove the extension, unify the slashes
@@ -75,14 +77,11 @@ namespace MaterialUtils
         static char cachedGameName[AZ_MAX_PATH_LEN] = { 0 };
         static char cachedGameName[AZ_MAX_PATH_LEN] = { 0 };
         if (!removals[removalSize - 1])
         if (!removals[removalSize - 1])
         {
         {
-            if ((gEnv) && (gEnv->pConsole))
+            auto projectName = AZ::Utils::GetProjectName();
+            if (!projectName.empty())
             {
             {
-                ICVar* pGameNameCVar = gEnv->pConsole->GetCVar("sys_game_folder");
-                if (pGameNameCVar)
-                {
-                    azstrcpy(cachedGameName, AZ_MAX_PATH_LEN, pGameNameCVar->GetString());
-                    azstrcat(cachedGameName, AZ_MAX_PATH_LEN, "/");
-                }
+                azstrcpy(cachedGameName, AZ_MAX_PATH_LEN, projectName.c_str());
+                azstrcat(cachedGameName, AZ_MAX_PATH_LEN, "/");
             }
             }
 
 
             if (cachedGameName[0] == 0)
             if (cachedGameName[0] == 0)

+ 0 - 18
Code/CryEngine/CryCommon/Mocks/ISystemMock.h

@@ -55,8 +55,6 @@ public:
         int());
         int());
     MOCK_METHOD0(GetLogicalCPUCount,
     MOCK_METHOD0(GetLogicalCPUCount,
         int());
         int());
-    MOCK_CONST_METHOD0(GetAssetsPlatform,
-        const char*());
     MOCK_CONST_METHOD0(GetRenderingDriverName,
     MOCK_CONST_METHOD0(GetRenderingDriverName,
         const char*());
         const char*());
     MOCK_METHOD1(DumpMemoryUsageStatistics,
     MOCK_METHOD1(DumpMemoryUsageStatistics,
@@ -206,22 +204,6 @@ public:
         bool());
         bool());
     MOCK_METHOD3(SetFrameProfiler,
     MOCK_METHOD3(SetFrameProfiler,
         void(bool on, bool display, char* prefix));
         void(bool on, bool display, char* prefix));
-    MOCK_METHOD2(StartLoadingSectionProfiling,
-        struct SLoadingTimeContainer*(CLoadingTimeProfiler * pProfiler, const char* szFuncName));
-    MOCK_METHOD1(EndLoadingSectionProfiling,
-        void(CLoadingTimeProfiler * pProfiler));
-    MOCK_METHOD2(StartBootSectionProfiler,
-        CBootProfilerRecord * (const char* name, const char* args));
-    MOCK_METHOD1(StopBootSectionProfiler,
-        void(CBootProfilerRecord * record));
-    MOCK_METHOD1(StartBootProfilerSessionFrames,
-        void(const char* pName));
-    MOCK_METHOD0(StopBootProfilerSessionFrames,
-        void());
-    MOCK_METHOD0(OutputLoadingTimeStats,
-        void());
-    MOCK_METHOD0(GetLoadingProfilerCallstack,
-        const char*());
     MOCK_METHOD0(GetFileVersion,
     MOCK_METHOD0(GetFileVersion,
         const SFileVersion&());
         const SFileVersion&());
     MOCK_METHOD0(GetProductVersion,
     MOCK_METHOD0(GetProductVersion,

+ 0 - 160
Code/CryEngine/CryCommon/ParseEngineConfig.h

@@ -1,160 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-// Original file Copyright Crytek GMBH or its affiliates, used under license.
-
-#pragma once
-
-#include "ISystem.h"
-#include <AzCore/base.h>
-#include <AzCore/IO/SystemFile.h>
-#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
-#include <AzCore/Utils/Utils.h>
-#include <AzFramework/Platform/PlatformDefaults.h>
-
-// any of the following tags can be present in the bootstrap.cfg
-// you can also prefix it with a platform.
-// so for example, you can specify remote_ip alone to specify it for all platforms
-// or you could specify android_remote_ip to change it for android only.
-// the instructions are executed in the order that they appear, so you can set the default
-// by using the non-platform-specific version, and then later on in the file you
-// can override specific platforms.
-
-#define CONFIG_KEY_FOR_REMOTEIP                 "remote_ip"
-#define CONFIG_KEY_FOR_REMOTEPORT               "remote_port"
-#define CONFIG_KEY_FOR_GAMEFOLDER               "sys_game_folder"
-#define CONFIG_KEY_FOR_REMOTEFILEIO             "remote_filesystem"
-#define CONFIG_KEY_FOR_CONNECTTOREMOTE          "connect_to_remote"
-#define CONFIG_KEY_WAIT_FOR_CONNECT             "wait_for_connect"
-#define DEFAULT_GAMEDLL                         "EmptyTemplate"
-#define DEFAULT_GAMEFOLDER                      "EmptyTemplate"
-#define DEFAULT_REMOTEIP                        "127.0.0.1"
-#define DEFAULT_REMOTEPORT                      45643
-#define CONFIG_KEY_FOR_ASSETS                   "assets"
-#define CONFIG_KEY_FOR_BRANCHTOKEN              "assetProcessor_branch_token"
-
-//////////////////////////////////////////////////////////////////////////
-class CEngineConfig
-{
-public:
-    string m_gameFolder; // folder only ("MyGame")
-    string m_assetPlatform; // what platform folder assets are from if more than one is available or using VFS ("pc" / "es3")
-    bool   m_connectToRemote;
-    bool   m_remoteFileIO;
-    bool   m_waitForConnect;
-    string m_remoteIP;
-    int    m_remotePort;
-
-    string m_rootFolder; // The engine root folder
-    string m_branchToken;
-
-    CEngineConfig([[maybe_unused]] const char** sourcePaths = nullptr, [[maybe_unused]] size_t numSearchPaths = 0, [[maybe_unused]] size_t numLevelsUp = 3)
-        : m_gameFolder(DEFAULT_GAMEFOLDER)
-        , m_connectToRemote(false)
-        , m_remoteFileIO(false)
-        , m_remotePort(DEFAULT_REMOTEPORT)
-        , m_waitForConnect(false)
-        , m_remoteIP(DEFAULT_REMOTEIP)
-    {
-        m_assetPlatform = AzFramework::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
-
-        if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
-        {
-            AZ::SettingsRegistryInterface::FixedValueString gameFolder;
-            auto gameFolderKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/%s",
-                AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey, CONFIG_KEY_FOR_GAMEFOLDER);
-            if (settingsRegistry->Get(gameFolder, gameFolderKey))
-            {
-                m_gameFolder.assign(gameFolder.c_str(), gameFolder.size());
-            }
-
-            AZ::SettingsRegistryInterface::FixedValueString engineRoot;
-            if (settingsRegistry->Get(engineRoot, AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder))
-            {
-                m_rootFolder.assign(engineRoot.c_str(), engineRoot.size());
-            }
-        }
-
-        OnLoadSettings();
-    }
-
-    void CopyToStartupParams(SSystemInitParams& startupParams) const
-    {
-        startupParams.remoteFileIO = m_remoteFileIO;
-        startupParams.remotePort = m_remotePort;
-        startupParams.connectToRemote = m_connectToRemote;
-        startupParams.waitForConnection = m_waitForConnect;
-
-        azstrncpy(startupParams.remoteIP, sizeof(startupParams.remoteIP), m_remoteIP.c_str(), m_remoteIP.length() + 1); // +1 for the null terminator
-        azstrncpy(startupParams.assetsPlatform, sizeof(startupParams.assetsPlatform), m_assetPlatform.c_str(), m_assetPlatform.length() + 1); // +1 for the null terminator
-        azstrncpy(startupParams.rootPath, sizeof(startupParams.rootPath), m_rootFolder.c_str(), m_rootFolder.length() + 1); // +1 for the null terminator
-        azstrncpy(startupParams.gameFolderName, sizeof(startupParams.gameFolderName), m_gameFolder.c_str(), m_gameFolder.length() + 1); // +1 for the null terminator
-        azstrncpy(startupParams.branchToken, sizeof(startupParams.branchToken), m_branchToken.c_str(), m_branchToken.length() + 1); // +1 for the null terminator
-
-        // compute assets path based on game folder name
-        string gameFolderLower(m_gameFolder);
-        gameFolderLower.MakeLower();
-        azsnprintf(startupParams.assetsPath, sizeof(startupParams.assetsPath), "%s/%s", startupParams.rootPath, gameFolderLower.c_str());
-
-        // compute where the cache should be located
-        azsnprintf(startupParams.rootPathCache, sizeof(startupParams.rootPathCache), "%s/Cache/%s/%s", m_rootFolder.c_str(), m_gameFolder.c_str(), m_assetPlatform.c_str());
-        azsnprintf(startupParams.assetsPathCache, sizeof(startupParams.assetsPathCache), "%s/%s", startupParams.rootPathCache, gameFolderLower.c_str());
-    }
-
-protected:
-
-    void OnLoadSettings()
-    {
-        auto settingsRegistry = AZ::SettingsRegistry::Get();
-        if (settingsRegistry == nullptr)
-        {
-            AZ_Warning("ParseEngineConfig", false, "Attempting to load configuration data while SettingsRegistry does not exist");
-            return;
-
-        }
-        AZ::SettingsRegistryInterface::FixedValueString settingsKeyPrefix = AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey;
-        AZ::SettingsRegistryInterface::FixedValueString settingsValueString;
-        AZ::s64 settingsValueInt{};
-
-        if (AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, settingsValueInt, settingsKeyPrefix, CONFIG_KEY_FOR_REMOTEFILEIO))
-        {
-            m_remoteFileIO = settingsValueInt != 0;
-        }
-        if (AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, settingsValueInt, settingsKeyPrefix, CONFIG_KEY_WAIT_FOR_CONNECT))
-        {
-            m_waitForConnect = settingsValueInt != 0;
-        }
-        if (AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, settingsValueInt, settingsKeyPrefix, CONFIG_KEY_FOR_CONNECTTOREMOTE))
-        {
-            m_connectToRemote = settingsValueInt != 0;
-        }
-        if (AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, settingsValueInt, settingsKeyPrefix, CONFIG_KEY_FOR_REMOTEPORT))
-        {
-            m_remotePort = aznumeric_cast<AZ::u16>(settingsValueInt);
-        }
-        if (settingsValueString = {};
-            AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, settingsValueString, settingsKeyPrefix, CONFIG_KEY_FOR_REMOTEIP))
-        {
-            m_remoteIP.assign(settingsValueString.c_str(), settingsValueString.size());
-        }
-        if (settingsValueString = {};
-            AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, settingsValueString, settingsKeyPrefix, CONFIG_KEY_FOR_ASSETS))
-        {
-            m_assetPlatform.assign(settingsValueString.c_str(), settingsValueString.size());
-        }
-        if (settingsValueString = {};
-            settingsRegistry->Get(settingsValueString, settingsKeyPrefix + "/" + CONFIG_KEY_FOR_BRANCHTOKEN))
-        {
-            m_branchToken.assign(settingsValueString.c_str(), settingsValueString.size());
-        }
-        
-    }
-};

+ 1 - 1
Code/CryEngine/CryCommon/ProjectDefines.h

@@ -293,7 +293,7 @@ typedef uint32 vtx_idx;
 
 
 #if defined(ENABLE_PROFILING_CODE)
 #if defined(ENABLE_PROFILING_CODE)
 #   define USE_DISK_PROFILER
 #   define USE_DISK_PROFILER
-//#   define ENABLE_LOADING_PROFILER    // Not guaranteed to have enough slots for all the threads in the system
+#   define ENABLE_LOADING_PROFILER  // requires AZ_PROFILE_TELEMETRY to also be defined
 #endif
 #endif
 
 
 #if defined(SOFTCODE_ENABLED)
 #if defined(SOFTCODE_ENABLED)

+ 0 - 1
Code/CryEngine/CryCommon/crycommon_files.cmake

@@ -110,7 +110,6 @@ set(FILES
     AzDXGIFormat.h
     AzDXGIFormat.h
     SFunctor.h
     SFunctor.h
     FunctorBaseFunction.h
     FunctorBaseFunction.h
-    ParseEngineConfig.h
     CustomMemoryHeap.h
     CustomMemoryHeap.h
     FunctorBaseMember.h
     FunctorBaseMember.h
     stridedptr.h
     stridedptr.h

+ 0 - 630
Code/CryEngine/CrySystem/BootProfiler.cpp

@@ -1,630 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-// Original file Copyright Crytek GMBH or its affiliates, used under license.
-
-#include "CrySystem_precompiled.h"
-
-#if defined(ENABLE_LOADING_PROFILER)
-
-#include "BootProfiler.h"
-#include "ThreadInfo.h"
-#include <stack>
-#include <AzFramework/IO/FileOperations.h>
-
-
-namespace
-{
-    StaticInstance<CBootProfiler, AZStd::no_destruct<CBootProfiler>> gProfilerInstance;
-    enum
-    {
-        eMAX_THREADS_TO_PROFILE = 128,
-        eNUM_RECORDS_PER_POOL = 2048, // so, eNUM_RECORDS_PER_POOL * sizeof(CBootProfilerRecord) == mem consumed by pool item
-        // sizeof(CProfileBlockTimes)==152,
-        // poolmem = 304Kb for 1 pool per thread
-    };
-}
-
-int CBootProfiler::CV_sys_bp_frames = 0;
-float CBootProfiler::CV_sys_bp_time_threshold = 0;
-
-class CProfileBlockTimes
-{
-protected:
-    LARGE_INTEGER m_startTimeStamp;
-    LARGE_INTEGER m_stopTimeStamp;
-    LARGE_INTEGER m_freq;
-    CProfileBlockTimes()
-    {
-        memset(&m_startTimeStamp, 0, sizeof(m_startTimeStamp));
-        memset(&m_stopTimeStamp, 0, sizeof(m_stopTimeStamp));
-        memset(&m_freq, 0, sizeof(m_freq));
-    }
-};
-
-class CBootProfilerRecord
-{
-public:
-    const char* m_label;
-    LARGE_INTEGER m_startTimeStamp;
-    LARGE_INTEGER m_stopTimeStamp;
-    LARGE_INTEGER m_freq;
-
-    CBootProfilerRecord* m_pParent;
-    typedef AZStd::vector<CBootProfilerRecord*> ChildVector;
-    ChildVector m_Childs;
-
-    CryFixedStringT<256> m_args;
-
-    ILINE CBootProfilerRecord(const char* label, LARGE_INTEGER timestamp, LARGE_INTEGER freq, const char* args)
-        : m_label(label)
-        , m_startTimeStamp(timestamp)
-        , m_freq(freq)
-        , m_pParent(NULL)
-    {
-        memset(&m_stopTimeStamp, 0, sizeof(m_stopTimeStamp));
-        if (args)
-        {
-            m_args = args;
-        }
-    }
-
-    ILINE ~CBootProfilerRecord()
-    {
-        // childs are allocated via pool as well, the destructors of each child
-        // is called explicitly, for the purpose of freeing memory occupied by
-        // m_Child vector. Otherwise there will be a memory leak.
-        ChildVector::iterator it = m_Childs.begin();
-        while (it != m_Childs.end())
-        {
-            (*it)->~CBootProfilerRecord();
-            ++it;
-        }
-    }
-
-    void Print(AZ::IO::HandleType fileHandle, char* buf, size_t buf_size, size_t depth, LARGE_INTEGER stopTime, const char* threadName, const float timeThreshold)
-    {
-        if (m_stopTimeStamp.QuadPart == 0)
-        {
-            m_stopTimeStamp = stopTime;
-        }
-
-        const float time = (float)(m_stopTimeStamp.QuadPart - m_startTimeStamp.QuadPart) * 1000.f / (float)m_freq.QuadPart;
-
-        if (timeThreshold > 0.0f && time < timeThreshold)
-        {
-            return;
-        }
-
-        string tabs; //tabs(depth++, '\t')
-        tabs.insert(0, depth++, '\t');
-
-        {
-            string label = m_label;
-            label.replace("&", "&amp;");
-            label.replace("<", "&lt;");
-            label.replace(">", "&gt;");
-            label.replace("\"", "&quot;");
-            label.replace("'", "&apos;");
-
-            if (m_args.size() > 0)
-            {
-                m_args.replace("&", "&amp;");
-                m_args.replace("<", "&lt;");
-                m_args.replace(">", "&gt;");
-                m_args.replace("\"", "&quot;");
-                m_args.replace("'", "&apos;");
-                m_args.replace("%", "&#37;");
-            }
-
-            sprintf_s(buf, buf_size, "%s<block name=\"%s\" totalTimeMS=\"%f\" startTime=\"%" PRIu64 "\" stopTime=\"%" PRIu64 "\" args=\"%s\"> \n",
-                tabs.c_str(), label.c_str(), time, m_startTimeStamp.QuadPart, m_stopTimeStamp.QuadPart, m_args.c_str());
-            AZ::IO::Print(fileHandle, buf);
-        }
-
-        const size_t childsSize = m_Childs.size();
-        for (size_t i = 0; i < childsSize; ++i)
-        {
-            CBootProfilerRecord* record = m_Childs[i];
-            assert(record);
-            record->Print(fileHandle, buf, buf_size, depth, stopTime, threadName, timeThreshold);
-        }
-
-        sprintf_s(buf, buf_size, "%s</block>\n", tabs.c_str());
-        AZ::IO::Print(fileHandle, buf);
-    }
-};
-
-//////////////////////////////////////////////////////////////////////////
-
-class CProfileInfo
-{
-    friend class CBootProfilerSession;
-private:
-    CBootProfilerRecord* m_pRoot;
-    CBootProfilerRecord* m_pCurrent;
-public:
-    CProfileInfo()
-        : m_pRoot(NULL)
-        , m_pCurrent(NULL) {}
-};
-
-
-class CBootProfilerThreadsInterface
-{
-protected:
-    CBootProfilerThreadsInterface()
-    {
-        memset(m_threadInfo, 0, sizeof(m_threadInfo));
-        m_threadCounter = 0;
-    }
-
-    unsigned int GetThreadIndexByID(unsigned int threadID);
-    const char* GetThreadNameByIndex(unsigned int threadIndex);
-
-    int m_threadCounter;
-private:
-    unsigned int m_threadInfo[eMAX_THREADS_TO_PROFILE]; //threadIDs
-};
-
-//////////////////////////////////////////////////////////////////////////
-ILINE unsigned int CBootProfilerThreadsInterface::GetThreadIndexByID(unsigned int threadID)
-{
-    for (int i = 0; i < eMAX_THREADS_TO_PROFILE; ++i)
-    {
-        if (m_threadInfo[i] == 0)
-        {
-            break;
-        }
-        if (m_threadInfo[i] == threadID)
-        {
-            return i;
-        }
-    }
-
-    unsigned int counter = CryInterlockedIncrement(&m_threadCounter) - 1; //count to index
-    m_threadInfo[counter] = threadID;
-
-    return counter;
-}
-
-ILINE const char* CBootProfilerThreadsInterface::GetThreadNameByIndex(unsigned int threadIndex)
-{
-    assert(threadIndex < m_threadCounter);
-
-    const char* threadName = CryThreadGetName(m_threadInfo[threadIndex]);
-    return threadName;
-}
-
-class CRecordPool
-{
-public:
-    CRecordPool()
-        : m_baseAddr(NULL)
-        , m_allocCounter(0)
-        , m_next(NULL)
-    {
-        m_baseAddr = (CBootProfilerRecord*)CryModuleMemalign(eNUM_RECORDS_PER_POOL *    sizeof(CBootProfilerRecord), 16);
-    }
-    ~CRecordPool()
-    {
-        CryModuleMemalignFree(m_baseAddr);
-        delete m_next;
-    }
-
-    ILINE CBootProfilerRecord* allocateRecord()
-    {
-        if (m_allocCounter < eNUM_RECORDS_PER_POOL)
-        {
-            CBootProfilerRecord* newRecord = m_baseAddr + m_allocCounter;
-            ++m_allocCounter;
-            return newRecord;
-        }
-        else
-        {
-            return NULL;
-        }
-    }
-
-    ILINE void setNextPool(CRecordPool* pool) { m_next = pool; }
-
-private:
-    CBootProfilerRecord* m_baseAddr;
-    uint32 m_allocCounter;
-
-    CRecordPool* m_next;
-};
-
-class CBootProfilerSession
-    : public CBootProfilerThreadsInterface
-    , protected CProfileBlockTimes
-{
-public:
-    CBootProfilerSession();
-    ~CBootProfilerSession();
-
-    void Start();
-    void Stop();
-
-    CBootProfilerRecord* StartBlock(const char* name, const char* args);
-    void StopBlock(CBootProfilerRecord* record);
-
-    void CollectResults(const char* filename, const float timeThreshold);
-
-private:
-    string m_name;
-
-    CProfileInfo m_threadsProfileInfo[eMAX_THREADS_TO_PROFILE];
-    CRecordPool* m_threadsRecordsPool[eMAX_THREADS_TO_PROFILE];     //head
-    CRecordPool* m_threadsCurrentPools[eMAX_THREADS_TO_PROFILE];  //current
-};
-
-
-//////////////////////////////////////////////////////////////////////////
-
-CBootProfilerSession::CBootProfilerSession()
-{
-    memset(m_threadsProfileInfo, 0, sizeof(m_threadsProfileInfo));
-
-    memset(m_threadsRecordsPool, 0, sizeof(m_threadsRecordsPool));
-    memset(m_threadsCurrentPools, 0, sizeof(m_threadsCurrentPools));
-}
-
-CBootProfilerSession::~CBootProfilerSession()
-{
-    for (unsigned int i = 0; i < m_threadCounter; ++i)
-    {
-        CProfileInfo& profile = m_threadsProfileInfo[i];
-
-        // Since m_pRoot is allocated using memory pool (line 296),
-        // its destructor is called explicitly to free the memory of
-        // m_Childs and each of its child.
-
-        if (profile.m_pRoot)
-        {
-            profile.m_pRoot->~CBootProfilerRecord();
-        }
-        delete m_threadsRecordsPool[i];
-    }
-}
-
-void CBootProfilerSession::Start()
-{
-    LARGE_INTEGER time, freq;
-    QueryPerformanceFrequency(&freq);
-    QueryPerformanceCounter(&time);
-    m_startTimeStamp = time;
-    m_freq = freq;
-}
-
-void CBootProfilerSession::Stop()
-{
-    LARGE_INTEGER time;
-    QueryPerformanceCounter(&time);
-    m_stopTimeStamp = time;
-}
-
-CBootProfilerRecord* CBootProfilerSession::StartBlock(const char* name, const char* args)
-{
-    const unsigned int curThread = CryGetCurrentThreadId();
-    const unsigned int threadIndex = GetThreadIndexByID(curThread);
-
-    assert(threadIndex < eMAX_THREADS_TO_PROFILE);
-
-    CProfileInfo& profile = m_threadsProfileInfo[threadIndex];
-
-    CRecordPool* pool = m_threadsCurrentPools[threadIndex];
-
-    if (!profile.m_pRoot)
-    {
-        if (!pool)
-        {
-            pool = new CRecordPool;
-            m_threadsRecordsPool[threadIndex] = pool;
-            m_threadsCurrentPools[threadIndex] = pool;
-        }
-
-        CBootProfilerRecord* rec = pool->allocateRecord();
-        profile.m_pRoot = profile.m_pCurrent = new(rec)CBootProfilerRecord("root", m_startTimeStamp, m_freq, args);
-    }
-
-    assert(pool);
-
-    LARGE_INTEGER time, freq;
-    QueryPerformanceFrequency(&freq);
-    QueryPerformanceCounter(&time);
-
-    CBootProfilerRecord* pParent = profile.m_pCurrent;
-    assert(pParent);
-    assert(profile.m_pRoot);
-
-    CBootProfilerRecord* rec = pool->allocateRecord();
-    if (!rec)
-    {
-        //pool is full, create a new one
-        pool = new CRecordPool;
-        m_threadsCurrentPools[threadIndex]->setNextPool(pool);
-        m_threadsCurrentPools[threadIndex] = pool;
-
-        rec = pool->allocateRecord();
-    }
-
-    profile.m_pCurrent = new(rec)CBootProfilerRecord(name, time, freq, args);
-    profile.m_pCurrent->m_pParent = pParent;
-    pParent->m_Childs.push_back(profile.m_pCurrent);
-
-    return profile.m_pCurrent;
-}
-
-void CBootProfilerSession::StopBlock(CBootProfilerRecord* record)
-{
-    if (record)
-    {
-        LARGE_INTEGER time;
-        QueryPerformanceCounter(&time);
-        record->m_stopTimeStamp = time;
-
-        unsigned int curThread = CryGetCurrentThreadId();
-        unsigned int threadIndex = GetThreadIndexByID(curThread);
-        assert(threadIndex < eMAX_THREADS_TO_PROFILE);
-
-        CProfileInfo& profile = m_threadsProfileInfo[threadIndex];
-        profile.m_pCurrent = record->m_pParent;
-    }
-}
-
-void CBootProfilerSession::CollectResults(const char* filename, const float timeThreshold)
-{
-    if (!gEnv || !gEnv->pCryPak)
-    {
-        AZ_Warning("BootProfiler", false, "CryPak not set - skipping CollectResults");
-        return;
-    }
-    static const char* szTestResults = "@cache@\\TestResults";
-    string filePath = string(szTestResults) + "\\" + "bp_" + filename + ".xml";
-    char path[AZ::IO::IArchive::MaxPath] = "";
-    gEnv->pCryPak->AdjustFileName(filePath.c_str(), path, AZ_ARRAY_SIZE(path), AZ::IO::IArchive::FLAGS_PATH_REAL | AZ::IO::IArchive::FLAGS_FOR_WRITING);
-    gEnv->pCryPak->MakeDir(szTestResults);
-
-    AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
-    gEnv->pFileIO->Open(path, AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary, fileHandle);
-    if (fileHandle == AZ::IO::InvalidHandle)
-    {
-        return;
-    }
-
-    char buf[512];
-    const unsigned int buf_size = sizeof(buf);
-
-    sprintf_s(buf, buf_size, "<root>\n");
-    AZ::IO::Print(fileHandle, buf);
-
-    const size_t numThreads = m_threadCounter;
-    for (size_t i = 0; i < numThreads; ++i)
-    {
-        CBootProfilerRecord* pRoot = m_threadsProfileInfo[i].m_pRoot;
-        if (pRoot)
-        {
-            pRoot->m_stopTimeStamp = m_stopTimeStamp;
-
-            const char* threadName = GetThreadNameByIndex(i);
-            if (!threadName)
-            {
-                threadName = "UNKNOWN";
-            }
-
-
-            const float time = (float)(pRoot->m_stopTimeStamp.QuadPart - pRoot->m_startTimeStamp.QuadPart) * 1000.f / (float)pRoot->m_freq.QuadPart;
-
-            sprintf_s(buf, buf_size, "\t<thread name=\"%s\" totalTimeMS=\"%f\" startTime=\"%" PRIu64 "\" stopTime=\"%" PRIu64 "\" > \n", threadName, time,
-                pRoot->m_startTimeStamp.QuadPart, pRoot->m_stopTimeStamp.QuadPart);
-            AZ::IO::Print(fileHandle, buf);
-
-            for (size_t recordIdx = 0; recordIdx < pRoot->m_Childs.size(); ++recordIdx)
-            {
-                CBootProfilerRecord* record = pRoot->m_Childs[recordIdx];
-                assert(record);
-                record->Print(fileHandle, buf, buf_size, 2, m_stopTimeStamp, threadName, timeThreshold);
-            }
-
-            sprintf_s(buf, buf_size, "\t</thread>\n");
-            AZ::IO::Print(fileHandle, buf);
-        }
-    }
-
-    sprintf_s(buf, buf_size, "</root>\n");
-    AZ::IO::Print(fileHandle, buf);
-    gEnv->pFileIO->Close(fileHandle);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////
-
-CBootProfiler& CBootProfiler::GetInstance()
-{
-    return gProfilerInstance;
-}
-
-CBootProfiler::CBootProfiler()
-    : m_pCurrentSession(NULL)
-    , m_pFrameRecord(NULL)
-    , m_levelLoadAdditionalFrames(0)
-{
-}
-
-CBootProfiler::~CBootProfiler()
-{
-    AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
-    for (TSessionMap::iterator it = m_sessions.begin(); it != m_sessions.end(); ++it)
-    {
-        CBootProfilerSession* session = it->second;
-        delete session;
-    }
-}
-
-// start session
-void CBootProfiler::StartSession(const char* sessionName)
-{
-    AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
-
-    TSessionMap::const_iterator it = m_sessions.find(sessionName);
-    if (it == m_sessions.end())
-    {
-        m_pCurrentSession = new CBootProfilerSession();
-        m_sessions[sessionName] = m_pCurrentSession;
-        m_pCurrentSession->Start();
-    }
-}
-
-// stop session
-void CBootProfiler::StopSession(const char* sessionName)
-{
-    AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
-    if (m_pCurrentSession)
-    {
-        TSessionMap::iterator it = m_sessions.find(sessionName);
-        if (it != m_sessions.end())
-        {
-            if (m_pCurrentSession == it->second)
-            {
-                CBootProfilerSession* session = m_pCurrentSession;
-                m_pCurrentSession = NULL;
-
-                session->Stop();
-                session->CollectResults(sessionName, CV_sys_bp_time_threshold);
-
-                delete session;
-            }
-            m_sessions.erase(it);
-        }
-    }
-}
-
-CBootProfilerRecord* CBootProfiler::StartBlock(const char* name, const char* args)
-{
-    AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
-    if (m_pCurrentSession)
-    {
-        return m_pCurrentSession->StartBlock(name, args);
-    }
-    return NULL;
-}
-
-void CBootProfiler::StopBlock(CBootProfilerRecord* record)
-{
-    AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
-    if (m_pCurrentSession)
-    {
-        m_pCurrentSession->StopBlock(record);
-    }
-}
-
-void CBootProfiler::StartFrame(const char* name)
-{
-    AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
-    if (CV_sys_bp_frames)
-    {
-        StartSession("frames");
-        m_pFrameRecord = StartBlock(name, NULL);
-    }
-}
-
-void CBootProfiler::StopFrame()
-{
-    AZStd::lock_guard<AZStd::recursive_mutex> recordGuard{ m_recordMutex };
-    if (m_pCurrentSession && CV_sys_bp_frames)
-    {
-        StopBlock(m_pFrameRecord);
-        m_pFrameRecord = NULL;
-
-        --CV_sys_bp_frames;
-        if (0 == CV_sys_bp_frames)
-        {
-            StopSession("frames");
-        }
-    }
-
-    if (m_pCurrentSession && m_levelLoadAdditionalFrames)
-    {
-        --m_levelLoadAdditionalFrames;
-        if (0 == m_levelLoadAdditionalFrames)
-        {
-            StopSession("level");
-        }
-    }
-}
-
-void CBootProfiler::Init(ISystem* pSystem)
-{
-    //REGISTER_CVAR(sys_BootProfiler, 1, VF_DEV_ONLY,
-    //  "Collect and output session statistics into TestResults/bp_(session_name).xml   \n"
-    //  "0 = Disabled\n"
-    //  "1 = Enabled\n");
-
-    pSystem->GetISystemEventDispatcher()->RegisterListener(this);
-    StartSession("boot");
-}
-
-void CBootProfiler::RegisterCVars()
-{
-    REGISTER_CVAR2("sys_bp_frames", &CV_sys_bp_frames, 0, VF_DEV_ONLY, "Starts frame profiling for specified number of frames using BootProfiler");
-    REGISTER_CVAR2("sys_bp_time_threshold", &CV_sys_bp_time_threshold, 0.1f, VF_DEV_ONLY, "If greater than 0 don't write blocks that took less time (default 0.1 ms)");
-}
-
-void CBootProfiler::OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam)
-{
-    switch (event)
-    {
-    case ESYSTEM_EVENT_GAME_POST_INIT_DONE:
-    {
-        StopSession("boot");
-        break;
-    }
-    case ESYSTEM_EVENT_GAME_MODE_SWITCH_START:
-    {
-        break;
-    }
-
-    case ESYSTEM_EVENT_GAME_MODE_SWITCH_END:
-    {
-        break;
-    }
-
-    case ESYSTEM_EVENT_LEVEL_LOAD_START:
-    {
-        break;
-    }
-    case ESYSTEM_EVENT_LEVEL_LOAD_PREPARE:
-    {
-        StartSession("level");
-        break;
-    }
-    case ESYSTEM_EVENT_LEVEL_LOAD_END:
-    {
-        StopSession("level");
-        break;
-    }
-    case ESYSTEM_EVENT_LEVEL_PRECACHE_END:
-    {
-        //level loading can be stopped here, or m_levelLoadAdditionalFrames can be used to prolong dump for this amount of frames
-        //StopSession("level");
-        m_levelLoadAdditionalFrames = 20;
-        break;
-    }
-    }
-}
-
-void CBootProfiler::SetFrameCount(int frameCount)
-{
-    CV_sys_bp_frames = frameCount;
-}
-#endif

+ 0 - 67
Code/CryEngine/CrySystem/BootProfiler.h

@@ -1,67 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-// Original file Copyright Crytek GMBH or its affiliates, used under license.
-
-#ifndef CRYINCLUDE_CRYSYSTEM_BOOTPROFILER_H
-#define CRYINCLUDE_CRYSYSTEM_BOOTPROFILER_H
-#pragma once
-
-#if defined(ENABLE_LOADING_PROFILER)
-
-#include <AzCore/std/string/string.h>
-#include <AzCore/std/containers/unordered_map.h>
-#include <AzCore/std/parallel/mutex.h>
-
-class CBootProfilerRecord;
-class CBootProfilerSession;
-
-class CBootProfiler
-    : public ISystemEventListener
-{
-    friend class CBootProfileBLock;
-public:
-    CBootProfiler();
-    ~CBootProfiler();
-
-    static CBootProfiler& GetInstance();
-
-    void Init(ISystem* pSystem);
-    void RegisterCVars();
-
-    void StartSession(const char* sessionName);
-    void StopSession(const char* sessionName);
-
-    CBootProfilerRecord* StartBlock(const char* name, const char* args);
-    void StopBlock(CBootProfilerRecord* record);
-
-    void StartFrame(const char* name);
-    void StopFrame();
-protected:
-    // === ISystemEventListener
-    virtual void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam);
-    void SetFrameCount(int frameCount);
-
-private:
-    CBootProfilerSession* m_pCurrentSession;
-    typedef AZStd::unordered_map<AZStd::string, CBootProfilerSession*> TSessionMap;
-    TSessionMap m_sessions;
-
-    static int                      CV_sys_bp_frames;
-    static float                    CV_sys_bp_time_threshold;
-    CBootProfilerRecord*    m_pFrameRecord;
-    AZStd::recursive_mutex            m_recordMutex;
-    int m_levelLoadAdditionalFrames;
-};
-
-#endif
-
-#endif // CRYINCLUDE_CRYSYSTEM_BOOTPROFILER_H

+ 1 - 12
Code/CryEngine/CrySystem/DebugCallStack.cpp

@@ -277,17 +277,6 @@ int DebugCallStack::handleException(EXCEPTION_POINTERS* exception_pointer)
         sprintf_s(excCode, "0x%08X", exception_pointer->ExceptionRecord->ExceptionCode);
         sprintf_s(excCode, "0x%08X", exception_pointer->ExceptionRecord->ExceptionCode);
         WriteLineToLog("Exception: %s, at Address: %s", excCode, excAddr);
         WriteLineToLog("Exception: %s, at Address: %s", excCode, excAddr);
 
 
-        if (CSystem* pSystem = (CSystem*)GetSystem())
-        {
-            if (const char* pLoadingProfilerCallstack = pSystem->GetLoadingProfilerCallstack())
-            {
-                if (pLoadingProfilerCallstack[0])
-                {
-                    WriteLineToLog("<CrySystem> LoadingProfilerCallstack: %s", pLoadingProfilerCallstack);
-                }
-            }
-        }
-
         {
         {
             IMemoryManager::SProcessMemInfo memInfo;
             IMemoryManager::SProcessMemInfo memInfo;
             if (gEnv->pSystem->GetIMemoryManager()->GetProcessMemInfo(memInfo))
             if (gEnv->pSystem->GetIMemoryManager()->GetProcessMemInfo(memInfo))
@@ -593,7 +582,7 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
                                 AZ::Debug::SymbolStorage::DecodeFrames(frames, numFrames, lines);
                                 AZ::Debug::SymbolStorage::DecodeFrames(frames, numFrames, lines);
                                 for (unsigned int i2 = 0; i2 < numFrames; ++i2)
                                 for (unsigned int i2 = 0; i2 < numFrames; ++i2)
                                 {
                                 {
-                                    fprintf(f, "%2d) %s\n", numFrames - i2, lines[i2]); 
+                                    fprintf(f, "%2d) %s\n", numFrames - i2, lines[i2]);
                                 }
                                 }
                             }
                             }
                         }
                         }

+ 7 - 11
Code/CryEngine/CrySystem/IDebugCallStack.cpp

@@ -20,8 +20,8 @@
 #include "System.h"
 #include "System.h"
 #include <AzFramework/IO/FileOperations.h>
 #include <AzFramework/IO/FileOperations.h>
 #include <AzCore/NativeUI/NativeUIRequests.h>
 #include <AzCore/NativeUI/NativeUIRequests.h>
-
-#include <AzFramework/StringFunc/StringFunc.h>
+#include <AzCore/StringFunc/StringFunc.h>
+#include <AzCore/Utils/Utils.h>
 //#if !defined(LINUX)
 //#if !defined(LINUX)
 
 
 #include <ISystem.h>
 #include <ISystem.h>
@@ -186,21 +186,17 @@ AZ_PUSH_DISABLE_WARNING(4996, "-Wunknown-warning-option")
         }
         }
     }
     }
 
 
-    if (gEnv->pConsole)
-    {
-        if (ICVar*  pCVarGameDir = gEnv->pConsole->GetCVar("sys_game_folder"))
-        {
-            sprintf(s, "GameDir: %s\n", pCVarGameDir->GetString());
-            azstrcat(str, length, s);
-        }
-    }
+    AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
+    azstrcat(str, length, "ProjectDir: ");
+    azstrcat(str, length, projectPath.c_str());
+    azstrcat(str, length, "\n");
 
 
 #if AZ_LEGACY_CRYSYSTEM_TRAIT_DEBUGCALLSTACK_APPEND_MODULENAME
 #if AZ_LEGACY_CRYSYSTEM_TRAIT_DEBUGCALLSTACK_APPEND_MODULENAME
     GetModuleFileNameA(NULL, s, sizeof(s));
     GetModuleFileNameA(NULL, s, sizeof(s));
     
     
     // Log EXE filename only if possible (not full EXE path which could contain sensitive info)
     // Log EXE filename only if possible (not full EXE path which could contain sensitive info)
     AZStd::string exeName;
     AZStd::string exeName;
-    if (AzFramework::StringFunc::Path::GetFullFileName(s, exeName))
+    if (AZ::StringFunc::Path::GetFullFileName(s, exeName))
     {
     {
         azstrcat(str, length, "Executable: ");
         azstrcat(str, length, "Executable: ");
         azstrcat(str, length, exeName.c_str());
         azstrcat(str, length, exeName.c_str());

+ 0 - 647
Code/CryEngine/CrySystem/LoadingProfiler.cpp

@@ -1,647 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-// Original file Copyright Crytek GMBH or its affiliates, used under license.
-
-#include "CrySystem_precompiled.h"
-
-#if defined(ENABLE_LOADING_PROFILER)
-
-#include "System.h"
-#include "LoadingProfiler.h"
-
-#define LOADING_TIME_CONTAINER_MAX_TEXT_SIZE 1024
-#define MAX_LOADING_TIME_PROFILER_STACK_DEPTH 16
-
-//#define SAVE_SAVELEVELSTATS_IN_ROOT
-
-struct SLoadingTimeContainer
-    : public _i_reference_target_t
-{
-    SLoadingTimeContainer()     {}
-
-    SLoadingTimeContainer(SLoadingTimeContainer* pParent, const char* pPureFuncName, const int nRootIndex)
-    {
-        m_dSelfMemUsage = m_dTotalMemUsage = m_dSelfTime = m_dTotalTime = 0;
-        m_nCounter = 1;
-        m_pFuncName = pPureFuncName;
-        m_pParent = pParent;
-        m_nRootIndex = nRootIndex;
-    }
-
-    static int Cmp_SLoadingTimeContainer_Time(const void* v1, const void* v2)
-    {
-        SLoadingTimeContainer* pChunk1 = (SLoadingTimeContainer*)v1;
-        SLoadingTimeContainer* pChunk2 = (SLoadingTimeContainer*)v2;
-
-        if (pChunk1->m_dSelfTime > pChunk2->m_dSelfTime)
-        {
-            return -1;
-        }
-        else if (pChunk1->m_dSelfTime < pChunk2->m_dSelfTime)
-        {
-            return 1;
-        }
-
-        return 0;
-    }
-
-    static int Cmp_SLoadingTimeContainer_MemUsage(const void* v1, const void* v2)
-    {
-        SLoadingTimeContainer* pChunk1 = (SLoadingTimeContainer*)v1;
-        SLoadingTimeContainer* pChunk2 = (SLoadingTimeContainer*)v2;
-
-        if (pChunk1->m_dSelfMemUsage > pChunk2->m_dSelfMemUsage)
-        {
-            return -1;
-        }
-        else if (pChunk1->m_dSelfMemUsage < pChunk2->m_dSelfMemUsage)
-        {
-            return 1;
-        }
-
-        return 0;
-    }
-
-    static double GetUsedMemory(ISystem* pSysytem)
-    {
-        static IMemoryManager::SProcessMemInfo processMemInfo;
-        pSysytem->GetIMemoryManager()->GetProcessMemInfo(processMemInfo);
-        return double(processMemInfo.PagefileUsage) / double(1024 * 1024);
-    }
-
-
-    void Clear()
-    {
-        for (size_t i = 0, end = m_pChilds.size(); i < end; ++i)
-        {
-            delete m_pChilds[i];
-        }
-    }
-
-    ~SLoadingTimeContainer()
-    {
-        Clear();
-    }
-
-
-    double m_dSelfTime, m_dTotalTime;
-    double m_dSelfMemUsage, m_dTotalMemUsage;
-    uint32 m_nCounter;
-
-    const char* m_pFuncName;
-    SLoadingTimeContainer* m_pParent;
-    int m_nRootIndex;
-    std::vector<SLoadingTimeContainer*> m_pChilds;
-
-    DiskOperationInfo m_selfInfo;
-    DiskOperationInfo m_totalInfo;
-    bool m_bUsed;
-};
-
-bool operator== (const SLoadingTimeContainer& a, const SLoadingTimeContainer& b)
-{
-    return b.m_pFuncName == a.m_pFuncName;
-}
-
-bool operator== (const SLoadingTimeContainer& a, const char* b)
-{
-    return b == a.m_pFuncName;
-}
-
-
-SLoadingTimeContainer* CLoadingProfilerSystem::m_pCurrentLoadingTimeContainer = 0;
-SLoadingTimeContainer* CLoadingProfilerSystem::m_pRoot[2] = {0, 0};
-int CLoadingProfilerSystem::m_iActiveRoot = 0;
-ICVar* CLoadingProfilerSystem::m_pEnableProfile = 0;
-int CLoadingProfilerSystem::nLoadingProfileMode = 1;
-int CLoadingProfilerSystem::nLoadingProfilerNotTrackedAllocations = -1;
-CryCriticalSection CLoadingProfilerSystem::csLock;
-
-//////////////////////////////////////////////////////////////////////////
-void CLoadingProfilerSystem::OutputLoadingTimeStats(ILog* pLog, int nMode)
-{
-    nLoadingProfileMode = nMode;
-
-    PodArray<SLoadingTimeContainer> arrNoStack;
-    CreateNoStackList(arrNoStack);
-
-
-    if (nLoadingProfileMode > 0)
-    { // loading mem stats per func
-        pLog->Log("------ Level loading memory allocations (MB) by function ------------");
-        pLog->Log(" ||Self |  Total |  Calls | Function (%d MB lost)||", nLoadingProfilerNotTrackedAllocations);
-        pLog->Log("---------------------------------------------------------------------");
-
-        qsort(arrNoStack.GetElements(), arrNoStack.Count(), sizeof(arrNoStack[0]), SLoadingTimeContainer::Cmp_SLoadingTimeContainer_MemUsage);
-
-        for (int i = 0; i < arrNoStack.Count(); i++)
-        {
-            const SLoadingTimeContainer* pTimeContainer = &arrNoStack[i];
-            pLog->Log("|%6.1f | %6.1f | %6d | %s|",
-                pTimeContainer->m_dSelfMemUsage, pTimeContainer->m_dTotalMemUsage, (int)pTimeContainer->m_nCounter, pTimeContainer->m_pFuncName);
-        }
-
-        pLog->Log("---------------------------------------------------------------------");
-    }
-
-    if (nLoadingProfileMode > 0)
-    { // loading time stats per func
-        pLog->Log("----------- Level loading time (sec) by function --------------------");
-        pLog->Log(" ||Self |  Total |  Calls | Function||");
-        pLog->Log("---------------------------------------------------------------------");
-
-        qsort(arrNoStack.GetElements(), arrNoStack.Count(), sizeof(arrNoStack[0]), SLoadingTimeContainer::Cmp_SLoadingTimeContainer_Time);
-
-        for (int i = 0; i < arrNoStack.Count(); i++)
-        {
-            const SLoadingTimeContainer* pTimeContainer = &arrNoStack[i];
-            pLog->Log("|%6.1f | %6.1f | %6d | %s|",
-                pTimeContainer->m_dSelfTime, pTimeContainer->m_dTotalTime, (int)pTimeContainer->m_nCounter, pTimeContainer->m_pFuncName);
-        }
-
-        if (nLoadingProfileMode == 1)
-        {
-            pLog->Log("----- ( Use sys_ProfileLevelLoading 2 for more detailed stats ) -----");
-        }
-        else
-        {
-            pLog->Log("---------------------------------------------------------------------");
-        }
-    }
-
-    if (nLoadingProfileMode > 0)
-    { // file info
-        pLog->Log("----------------------------- Level file information by function --------------------------------");
-        pLog->Log("||           Self          |           Total         |Bandwith|  Calls | Function||");
-        pLog->Log("|| Seeks |FileOpen|FileRead| Seeks |FileOpen|FileRead|  Kb/s  |        |         ||");
-
-        qsort(arrNoStack.GetElements(), arrNoStack.Count(), sizeof(arrNoStack[0]), SLoadingTimeContainer::Cmp_SLoadingTimeContainer_Time);
-
-        for (int i = 0; i < arrNoStack.Count(); i++)
-        {
-            const SLoadingTimeContainer* pTimeContainer = &arrNoStack[i];
-            double bandwidth = pTimeContainer->m_dSelfTime > 0 ? (pTimeContainer->m_selfInfo.m_dOperationSize / pTimeContainer->m_dSelfTime / 1024.0) : 0.;
-            pLog->Log("|%6d | %6d | %6d |%6d | %6d | %6d | %6.1f | %6d | %s|",
-                pTimeContainer->m_selfInfo.m_nSeeksCount, pTimeContainer->m_selfInfo.m_nFileOpenCount, pTimeContainer->m_selfInfo.m_nFileReadCount,
-                pTimeContainer->m_totalInfo.m_nSeeksCount, pTimeContainer->m_totalInfo.m_nFileOpenCount, pTimeContainer->m_totalInfo.m_nFileReadCount,
-                bandwidth, (int)pTimeContainer->m_nCounter, pTimeContainer->m_pFuncName);
-        }
-
-        if (nLoadingProfileMode == 1)
-        {
-            pLog->Log("----- ( Use sys_ProfileLevelLoading 2 for more detailed stats ) -----");
-        }
-        else
-        {
-            pLog->Log("---------------------------------------------------------------------");
-        }
-    }
-}
-
-struct CSystemEventListner_LoadingProfiler
-    : public ISystemEventListener
-{
-private:
-    CLoadingTimeProfiler* m_pPrecacheProfiler;
-    ESystemEvent lastEvent;
-public:
-    CSystemEventListner_LoadingProfiler()
-        : m_pPrecacheProfiler(NULL) {}
-
-    virtual void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam)
-    {
-        switch (event)
-        {
-        case ESYSTEM_EVENT_GAME_MODE_SWITCH_START:
-        {
-            CLoadingProfilerSystem::Clean();
-            if (m_pPrecacheProfiler == NULL)
-            {
-                m_pPrecacheProfiler = new CLoadingTimeProfiler(gEnv->pSystem, "ModeSwitch");
-            }
-            break;
-        }
-
-        case ESYSTEM_EVENT_GAME_MODE_SWITCH_END:
-        {
-            SAFE_DELETE(m_pPrecacheProfiler);
-            CLoadingProfilerSystem::SaveTimeContainersToFile(gEnv->bMultiplayer == true ? "mode_switch_mp.lmbrlp" : "mode_switch_sp.lmbrlp", 0.0, true);
-        }
-
-        case ESYSTEM_EVENT_LEVEL_LOAD_PREPARE:
-        {
-            CLoadingProfilerSystem::Clean();
-            if (m_pPrecacheProfiler == NULL)
-            {
-                m_pPrecacheProfiler = new CLoadingTimeProfiler(gEnv->pSystem, "LevelLoading");
-            }
-            break;
-        }
-
-        case ESYSTEM_EVENT_LEVEL_LOAD_END:
-        {
-            delete m_pPrecacheProfiler;
-            m_pPrecacheProfiler = new CLoadingTimeProfiler(gEnv->pSystem, "Precache");
-            break;
-        }
-        case ESYSTEM_EVENT_LEVEL_PRECACHE_END:
-        {
-            if (lastEvent == ESYSTEM_EVENT_LEVEL_PRECACHE_FIRST_FRAME)
-            {
-                SAFE_DELETE(m_pPrecacheProfiler);
-                string levelName = "no_level";
-                ICVar* sv_map = gEnv->pConsole->GetCVar("sv_map");
-                if (sv_map)
-                {
-                    levelName = sv_map->GetString();
-                }
-
-                string levelNameFullProfile = levelName + "_LP.lmbrlp";
-                string levelNameThreshold = levelName + "_LP_OneSec.lmbrlp";
-                CLoadingProfilerSystem::SaveTimeContainersToFile(levelNameFullProfile.c_str(), 0.0, false);
-                CLoadingProfilerSystem::SaveTimeContainersToFile(levelNameThreshold.c_str(), 1.0, true);
-            }
-            break;
-        }
-        case ESYSTEM_EVENT_LEVEL_POST_UNLOAD:
-        {
-            // Ensure that the precache profiler is dead
-            SAFE_DELETE(m_pPrecacheProfiler);
-            break;
-        }
-        }
-
-        if (event != ESYSTEM_EVENT_RANDOM_SEED)
-        {
-            lastEvent = event;
-        }
-    }
-};
-
-static CSystemEventListner_LoadingProfiler g_system_event_listener_loadingProfiler;
-
-void CLoadingProfilerSystem::Init()
-{
-    gEnv->pSystem->GetISystemEventDispatcher()->RegisterListener(&g_system_event_listener_loadingProfiler);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void CLoadingProfilerSystem::ShutDown()
-{
-    if (gEnv && gEnv->pSystem && gEnv->pSystem->GetISystemEventDispatcher())
-    {
-        gEnv->pSystem->GetISystemEventDispatcher()->RemoveListener(&g_system_event_listener_loadingProfiler);
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////
-SLoadingTimeContainer* CLoadingProfilerSystem::StartLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler, const char* szFuncName)
-{
-    if (!nLoadingProfileMode || !gEnv->pConsole)
-    {
-        return NULL;
-    }
-
-    DWORD threadID = GetCurrentThreadId();
-
-    static DWORD dwMainThreadId = GetCurrentThreadId();
-    if (threadID != dwMainThreadId)
-    {
-        return NULL;
-    }
-
-    if (!m_pEnableProfile)
-    {
-        if (gEnv->pConsole)
-        {
-            m_pEnableProfile = gEnv->pConsole->GetCVar("sys_ProfileLevelLoading");
-            if (!m_pEnableProfile)
-            {
-                return 0;
-            }
-        }
-        else
-        {
-            return 0;
-        }
-    }
-
-    if (m_pEnableProfile->GetIVal() <= 0)
-    {
-        return 0;
-    }
-
-    //if (m_pCurrentLoadingTimeContainer == m_pRoot && strstr(szFuncName,"Open"))
-    //{
-    //  pProfiler->m_constructorInfo.m_nFileOpenCount +=1;
-    //}
-
-    CryAutoCriticalSection lock(csLock);
-
-    if (true /*pProfiler && pProfiler->m_pSystem*/)
-    {
-        ITimer* pTimer = pProfiler->m_pSystem->GetITimer();
-        pProfiler->m_fConstructorTime = pTimer->GetAsyncTime().GetSeconds();
-        pProfiler->m_fConstructorMemUsage = SLoadingTimeContainer::GetUsedMemory(pProfiler->m_pSystem);
-
-        DiskOperationInfo info;
-        pProfiler->m_constructorInfo = info;
-
-        if (nLoadingProfilerNotTrackedAllocations < 0)
-        {
-            nLoadingProfilerNotTrackedAllocations = (int)pProfiler->m_fConstructorMemUsage;
-        }
-    }
-
-    SLoadingTimeContainer* pParent = m_pCurrentLoadingTimeContainer;
-    if (!pParent)
-    {
-        pParent = m_pCurrentLoadingTimeContainer = m_pRoot[m_iActiveRoot] = new SLoadingTimeContainer(0, "Root", m_iActiveRoot);
-    }
-
-    for (size_t i = 0, end = m_pCurrentLoadingTimeContainer->m_pChilds.size(); i < end; ++i)
-    {
-        if (m_pCurrentLoadingTimeContainer->m_pChilds[i]->m_pFuncName == szFuncName)
-        {
-            assert(m_pCurrentLoadingTimeContainer->m_pChilds[i]->m_pParent == m_pCurrentLoadingTimeContainer);
-            assert(!m_pCurrentLoadingTimeContainer->m_pChilds[i]->m_bUsed);
-            m_pCurrentLoadingTimeContainer->m_pChilds[i]->m_bUsed = true;
-            m_pCurrentLoadingTimeContainer->m_pChilds[i]->m_nCounter++;
-            m_pCurrentLoadingTimeContainer = m_pCurrentLoadingTimeContainer->m_pChilds[i];
-            return m_pCurrentLoadingTimeContainer;
-        }
-    }
-
-    m_pCurrentLoadingTimeContainer = new SLoadingTimeContainer(pParent, szFuncName, pParent->m_nRootIndex);
-    m_pCurrentLoadingTimeContainer->m_bUsed = true;
-    {
-        // Need to iterate from the end than
-        pParent->m_pChilds.push_back(m_pCurrentLoadingTimeContainer);
-    }
-
-    return m_pCurrentLoadingTimeContainer;
-}
-
-void CLoadingProfilerSystem::EndLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler)
-{
-    if (!nLoadingProfileMode)
-    {
-        return;
-    }
-
-    static DWORD dwMainThreadId = GetCurrentThreadId();
-
-    if (GetCurrentThreadId() != dwMainThreadId)
-    {
-        return;
-    }
-
-    if (!pProfiler->m_pTimeContainer)
-    {
-        return;
-    }
-
-    CryAutoCriticalSection lock(csLock);
-
-    if (true /*pProfiler && pProfiler->m_pSystem*/)
-    {
-        ITimer* pTimer = pProfiler->m_pSystem->GetITimer();
-        double fSelfTime = pTimer->GetAsyncTime().GetSeconds() - pProfiler->m_fConstructorTime;
-        double fMemUsage = SLoadingTimeContainer::GetUsedMemory(pProfiler->m_pSystem);
-        double fSelfMemUsage = fMemUsage - pProfiler->m_fConstructorMemUsage;
-
-
-        if (fSelfTime < 0.0)
-        {
-            assert(0);
-        }
-        pProfiler->m_pTimeContainer->m_dSelfTime += fSelfTime;
-        pProfiler->m_pTimeContainer->m_dTotalTime += fSelfTime;
-        pProfiler->m_pTimeContainer->m_dSelfMemUsage += fSelfMemUsage;
-        pProfiler->m_pTimeContainer->m_dTotalMemUsage += fSelfMemUsage;
-
-        DiskOperationInfo info;
-        info -= pProfiler->m_constructorInfo;
-        pProfiler->m_pTimeContainer->m_totalInfo += info;
-        pProfiler->m_pTimeContainer->m_selfInfo += info;
-        pProfiler->m_pTimeContainer->m_bUsed = false;
-
-        SLoadingTimeContainer* pParent = pProfiler->m_pTimeContainer->m_pParent;
-        pParent->m_selfInfo -= info;
-        pParent->m_dSelfTime -= fSelfTime;
-        pParent->m_dSelfMemUsage -= fSelfMemUsage;
-        if (pProfiler->m_pTimeContainer->m_pParent && pProfiler->m_pTimeContainer->m_pParent->m_nRootIndex == m_iActiveRoot)
-        {
-            m_pCurrentLoadingTimeContainer = pProfiler->m_pTimeContainer->m_pParent;
-        }
-    }
-}
-
-const char* CLoadingProfilerSystem::GetLoadingProfilerCallstack()
-{
-    CryAutoCriticalSection lock(csLock);
-
-    static char szStack[1024];
-
-    szStack[0] = 0;
-
-    SLoadingTimeContainer* pC = m_pCurrentLoadingTimeContainer;
-
-    PodArray<SLoadingTimeContainer*> arrItems;
-
-    while (pC)
-    {
-        arrItems.Add(pC);
-        pC = pC->m_pParent;
-    }
-
-    for (int i = arrItems.Count() - 1; i >= 0; i--)
-    {
-        cry_strcat(szStack, " > ");
-        cry_strcat(szStack, arrItems[i]->m_pFuncName);
-    }
-
-    return &szStack[0];
-}
-
-void CLoadingProfilerSystem::FillProfilersList(AZStd::vector<SLoadingProfilerInfo>& profilers)
-{
-    UpdateSelfStatistics(m_pRoot[m_iActiveRoot]);
-
-    PodArray<SLoadingTimeContainer> arrNoStack;
-    CreateNoStackList(arrNoStack);
-    //qsort(arrNoStack.GetElements(), arrNoStack.Count(), sizeof(arrNoStack[0]), SLoadingTimeContainer::Cmp_SLoadingTimeContainer_Time);
-
-    uint32 count = arrNoStack.Size();
-    profilers.resize(count);
-
-    for (uint32 i = 0; i < count; ++i)
-    {
-        profilers[i].name = arrNoStack[i].m_pFuncName;
-        profilers[i].selfTime = arrNoStack[i].m_dSelfTime;
-        profilers[i].callsTotal = arrNoStack[i].m_nCounter;
-        profilers[i].totalTime = arrNoStack[i].m_dTotalTime;
-        profilers[i].memorySize = arrNoStack[i].m_dTotalMemUsage;
-        profilers[i].selfInfo = arrNoStack[i].m_selfInfo;
-        profilers[i].totalInfo = arrNoStack[i].m_totalInfo;
-    }
-}
-
-
-void CLoadingProfilerSystem::AddTimeContainerFunction(PodArray<SLoadingTimeContainer>& arrNoStack, SLoadingTimeContainer* node)
-{
-    if (!node)
-    {
-        return;
-    }
-
-    SLoadingTimeContainer* it = std::find(arrNoStack.begin(), arrNoStack.end(), node->m_pFuncName);
-
-    if (it ==  arrNoStack.end())
-    {
-        arrNoStack.push_back(*node);
-    }
-    else
-    {
-        it->m_dSelfMemUsage += node->m_dSelfMemUsage;
-        it->m_dSelfTime += node->m_dSelfTime;
-        it->m_dTotalMemUsage += node->m_dTotalMemUsage;
-        it->m_dTotalTime += node->m_dTotalTime;
-        it->m_nCounter += node->m_nCounter;
-        it->m_selfInfo += node->m_selfInfo;
-        it->m_totalInfo += node->m_totalInfo;
-    }
-
-    for (size_t i = 0, end = node->m_pChilds.size(); i < end; ++i)
-    {
-        AddTimeContainerFunction(arrNoStack, node->m_pChilds[i]);
-    }
-}
-
-void CLoadingProfilerSystem::CreateNoStackList(PodArray<SLoadingTimeContainer>& arrNoStack)
-{
-    AddTimeContainerFunction(arrNoStack, m_pRoot[m_iActiveRoot]);
-}
-
-#define g_szTestResults "@cache@\\TestResults"
-
-void CLoadingProfilerSystem::SaveTimeContainersToFile(const char* name, double fMinTotalTime, bool bClean)
-{
-    if (m_pRoot[m_iActiveRoot])
-    {
-        const char* levelName = name;
-        //Ignore any folders in the input name
-        const char* folder = strrchr(name, '/');
-        if (folder != NULL)
-        {
-            levelName = folder + 1;
-        }
-        char path[AZ::IO::IArchive::MaxPath];
-        path[sizeof(path) - 1] = 0;
-
-        gEnv->pCryPak->AdjustFileName(string(string(g_szTestResults) + "\\" + levelName).c_str(), path, AZ_ARRAY_SIZE(path), AZ::IO::IArchive::FLAGS_PATH_REAL | AZ::IO::IArchive::FLAGS_FOR_WRITING);
-        gEnv->pCryPak->MakeDir(g_szTestResults);
-
-        AZ::IO::HandleType handle = AZ::IO::InvalidHandle;
-
-        AZ::IO::Result f = AZ::IO::FileIOBase::GetInstance()->Open(path,AZ::IO::OpenMode::ModeWrite, handle);
-
-        if (handle != AZ::IO::InvalidHandle)
-        {
-            UpdateSelfStatistics(m_pRoot[m_iActiveRoot]);
-            WriteTimeContainerToFile(m_pRoot[m_iActiveRoot], handle, 0, fMinTotalTime);
-            AZ::IO::FileIOBase::GetInstance()->Close(handle);
-        }
-
-        if (bClean)
-        {
-            Clean();
-        }
-    }
-}
-
-void CLoadingProfilerSystem::WriteTimeContainerToFile(SLoadingTimeContainer* p, AZ::IO::HandleType &handle, unsigned int depth, double fMinTotalTime)
-{
-    if (p == NULL)
-    {
-        return;
-    }
-
-    if (p->m_dTotalTime < fMinTotalTime)
-    {
-        return;
-    }
-
-    CryFixedStringT<MAX_LOADING_TIME_PROFILER_STACK_DEPTH> sDepth;
-    for (unsigned int i = 0; i < depth; i++)
-    {
-        sDepth += "\t";
-    }
-
-    CryFixedStringT<128> str(p->m_pFuncName);
-    str.replace(':', '_');
-
-    char data[4096];
-    AZ::u64 bytesWritten;
-
-    azsnprintf(data, sizeof(data), "%s<%s selfTime='%f' selfMemory='%f' totalTime='%f' totalMemory='%f' count='%i' totalSeeks='%i' totalReads='%i' totalOpens='%i' totalDiskSize='%f' selfSeeks='%i' selfReads='%i' selfOpens='%i' selfDiskSize='%f'>\n",
-                                    sDepth.c_str(), str.c_str(), p->m_dSelfTime, p->m_dSelfMemUsage, p->m_dTotalTime, p->m_dTotalMemUsage, p->m_nCounter,
-                                    p->m_totalInfo.m_nSeeksCount, p->m_totalInfo.m_nFileReadCount, p->m_totalInfo.m_nFileOpenCount, p->m_totalInfo.m_dOperationSize,
-                                    p->m_selfInfo.m_nSeeksCount, p->m_selfInfo.m_nFileReadCount, p->m_selfInfo.m_nFileOpenCount, p->m_selfInfo.m_dOperationSize);
-
-    AZ::IO::FileIOBase::GetInstance()->Write(handle, data, strlen(data), &bytesWritten);
-
-    for (size_t i = 0, end = p->m_pChilds.size(); i < end; ++i)
-    {
-        WriteTimeContainerToFile(p->m_pChilds[i], handle, depth + 1, fMinTotalTime);
-    }
-
-    azsnprintf(data, sizeof(data), "%s</%s>\n", sDepth.c_str(), str.c_str());
-    AZ::IO::FileIOBase::GetInstance()->Write(handle, data, strlen(data), &bytesWritten);
-
-}
-
-void CLoadingProfilerSystem::UpdateSelfStatistics(SLoadingTimeContainer* p)
-{
-    if (p == NULL)
-    {
-        return;
-    }
-
-    p->m_dSelfMemUsage = 0;
-    p->m_dSelfTime = 0;
-    p->m_nCounter = 1;
-    p->m_selfInfo.m_dOperationSize = 0;
-    p->m_selfInfo.m_nFileOpenCount = 0;
-    p->m_selfInfo.m_nFileReadCount = 0;
-    p->m_selfInfo.m_nSeeksCount = 0;
-
-    for (size_t i = 0, end = p->m_pChilds.size(); i < end; ++i)
-    {
-        p->m_dTotalMemUsage += p->m_pChilds[i]->m_dTotalMemUsage;
-        p->m_dTotalTime += p->m_pChilds[i]->m_dTotalTime;
-        p->m_totalInfo += p->m_pChilds[i]->m_totalInfo;
-    }
-}
-
-void CLoadingProfilerSystem::Clean()
-{
-    m_iActiveRoot = (m_iActiveRoot + 1) % 2;
-    if (m_pRoot[m_iActiveRoot])
-    {
-        delete m_pRoot[m_iActiveRoot];
-    }
-    m_pCurrentLoadingTimeContainer = m_pRoot[m_iActiveRoot] = 0;
-}
-
-#endif

+ 0 - 69
Code/CryEngine/CrySystem/LoadingProfiler.h

@@ -1,69 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-// Original file Copyright Crytek GMBH or its affiliates, used under license.
-
-#ifndef CRYINCLUDE_CRYSYSTEM_LOADINGPROFILER_H
-#define CRYINCLUDE_CRYSYSTEM_LOADINGPROFILER_H
-#pragma once
-
-
-#if defined(ENABLE_LOADING_PROFILER)
-
-struct SLoadingTimeContainer;
-
-
-struct SLoadingProfilerInfo
-{
-    string name;
-    double selfTime;
-    double totalTime;
-    uint32 callsTotal;
-    double memorySize;
-
-    DiskOperationInfo selfInfo;
-    DiskOperationInfo totalInfo;
-};
-
-
-class CLoadingProfilerSystem
-{
-public:
-    static void Init();
-    static void ShutDown();
-    static void CreateNoStackList(PodArray<SLoadingTimeContainer>&);
-    static void OutputLoadingTimeStats(ILog* pLog, int nMode);
-    static SLoadingTimeContainer* StartLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler, const char* szFuncName);
-    static void EndLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler);
-    static const char* GetLoadingProfilerCallstack();
-    static void FillProfilersList(AZStd::vector<SLoadingProfilerInfo>& profilers);
-    static void FlushTimeContainers();
-    static void SaveTimeContainersToFile(const char*, double fMinTotalTime, bool bClean);
-    static void WriteTimeContainerToFile(SLoadingTimeContainer* p, AZ::IO::HandleType &handle, unsigned int depth, double fMinTotalTime);
-
-    static void UpdateSelfStatistics(SLoadingTimeContainer* p);
-    static void Clean();
-protected:
-    static void AddTimeContainerFunction(PodArray<SLoadingTimeContainer>&, SLoadingTimeContainer*);
-protected:
-    static int nLoadingProfileMode;
-    static int nLoadingProfilerNotTrackedAllocations;
-    static CryCriticalSection csLock;
-    static int m_iMaxArraySize;
-    static SLoadingTimeContainer* m_pCurrentLoadingTimeContainer;
-    static SLoadingTimeContainer* m_pRoot[2];
-    static int m_iActiveRoot;
-    static ICVar* m_pEnableProfile;
-};
-
-#endif
-
-#endif // CRYINCLUDE_CRYSYSTEM_LOADINGPROFILER_H

+ 4 - 6
Code/CryEngine/CrySystem/NotificationNetwork.cpp

@@ -16,6 +16,7 @@
 #include <ISystem.h>
 #include <ISystem.h>
 
 
 #include <AzCore/Socket/AzSocket.h>
 #include <AzCore/Socket/AzSocket.h>
+#include <AzCore/Utils/Utils.h>
 
 
 #undef LockDebug
 #undef LockDebug
 //#define LockDebug(str1,str2)  {string strMessage;strMessage.Format(str1,str2);if (m_clients.size())   OutputDebugString(strMessage.c_str());}
 //#define LockDebug(str1,str2)  {string strMessage;strMessage.Format(str1,str2);if (m_clients.size())   OutputDebugString(strMessage.c_str());}
@@ -46,16 +47,13 @@ public:
 
 
         const char* path = nullptr; // Don't call GetGameFolder here, it returns a full absolute path and we just really want the game name
         const char* path = nullptr; // Don't call GetGameFolder here, it returns a full absolute path and we just really want the game name
 
 
-        if (ICVar* pVar = gEnv->pConsole->GetCVar("sys_game_folder"))
-        {
-            path = pVar->GetString();
-        }
-        if (!path)
+        AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
+        if (projectPath.empty())
         {
         {
             return;
             return;
         }
         }
 
 
-        pNotificationNetwork->Send("SystemInfo", path, ::strlen(path) + 1);
+        pNotificationNetwork->Send("SystemInfo", projectPath.c_str(), projectPath.size());
     }
     }
 } g_queryNotification;
 } g_queryNotification;
 
 

+ 1 - 1
Code/CryEngine/CrySystem/StreamEngine/StreamEngine.cpp

@@ -1243,7 +1243,7 @@ namespace
             {
             {
                 char path[AZ::IO::IArchive::MaxPath];
                 char path[AZ::IO::IArchive::MaxPath];
                 path[sizeof(path) - 1] = 0;
                 path[sizeof(path) - 1] = 0;
-                gEnv->pCryPak->AdjustFileName("@cache@\\TestResults\\StreamingLog.txt", path, AZ_ARRAY_SIZE(path), AZ::IO::IArchive::FLAGS_PATH_REAL | AZ::IO::IArchive::FLAGS_FOR_WRITING);
+                gEnv->pCryPak->AdjustFileName("@usercache@\\TestResults\\StreamingLog.txt", path, AZ_ARRAY_SIZE(path), AZ::IO::IArchive::FLAGS_PATH_REAL | AZ::IO::IArchive::FLAGS_FOR_WRITING);
                 sFileName = path;
                 sFileName = path;
             }
             }
             AZ::IO::HandleType fileHandle = fxopen(sFileName, (bFirstTime) ? "wt" : "at");
             AZ::IO::HandleType fileHandle = fxopen(sFileName, (bFirstTime) ? "wt" : "at");

+ 12 - 28
Code/CryEngine/CrySystem/System.cpp

@@ -157,7 +157,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 #include "ServerThrottle.h"
 #include "ServerThrottle.h"
 #include "ILocalMemoryUsage.h"
 #include "ILocalMemoryUsage.h"
 #include "ResourceManager.h"
 #include "ResourceManager.h"
-#include "LoadingProfiler.h"
 #include "HMDBus.h"
 #include "HMDBus.h"
 #include "OverloadSceneManager/OverloadSceneManager.h"
 #include "OverloadSceneManager/OverloadSceneManager.h"
 #include <IThreadManager.h>
 #include <IThreadManager.h>
@@ -168,7 +167,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 #include "IZStdDecompressor.h"
 #include "IZStdDecompressor.h"
 #include "zlib.h"
 #include "zlib.h"
 #include "RemoteConsole/RemoteConsole.h"
 #include "RemoteConsole/RemoteConsole.h"
-#include "BootProfiler.h"
 
 
 #include <PNoise3.h>
 #include <PNoise3.h>
 #include <StringUtils.h>
 #include <StringUtils.h>
@@ -320,10 +318,6 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
     m_bIsAsserting = false;
     m_bIsAsserting = false;
     m_pSystemEventDispatcher = new CSystemEventDispatcher(); // Must be first.
     m_pSystemEventDispatcher = new CSystemEventDispatcher(); // Must be first.
 
 
-#if defined(ENABLE_LOADING_PROFILER)
-    CBootProfiler::GetInstance().Init(this);
-#endif
-
     if (m_pSystemEventDispatcher)
     if (m_pSystemEventDispatcher)
     {
     {
         m_pSystemEventDispatcher->RegisterListener(this);
         m_pSystemEventDispatcher->RegisterListener(this);
@@ -422,7 +416,6 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
     //  m_sys_filecache = NULL;
     //  m_sys_filecache = NULL;
     m_gpu_particle_physics = NULL;
     m_gpu_particle_physics = NULL;
     m_pCpu = NULL;
     m_pCpu = NULL;
-    m_sys_game_folder = NULL;
 
 
     m_bInitializedSuccessfully = false;
     m_bInitializedSuccessfully = false;
     m_bShaderCacheGenMode = false;
     m_bShaderCacheGenMode = false;
@@ -634,10 +627,6 @@ void CSystem::ShutDown()
         EBUS_EVENT(CrySystemEventBus, OnCrySystemShutdown, *this);
         EBUS_EVENT(CrySystemEventBus, OnCrySystemShutdown, *this);
     }
     }
 
 
-#if defined(ENABLE_LOADING_PROFILER)
-    CLoadingProfilerSystem::ShutDown();
-#endif
-
     if (m_pUserCallback)
     if (m_pUserCallback)
     {
     {
         m_pUserCallback->OnShutdown();
         m_pUserCallback->OnShutdown();
@@ -657,7 +646,7 @@ void CSystem::ShutDown()
     SAFE_DELETE(m_pTextModeConsole);
     SAFE_DELETE(m_pTextModeConsole);
 
 
     KillPhysicsThread();
     KillPhysicsThread();
-    
+
     if (m_sys_firstlaunch)
     if (m_sys_firstlaunch)
     {
     {
         m_sys_firstlaunch->Set("0");
         m_sys_firstlaunch->Set("0");
@@ -828,7 +817,7 @@ void CSystem::ShutDown()
 void CSystem::Quit()
 void CSystem::Quit()
 {
 {
     CryLogAlways("CSystem::Quit invoked from thread %" PRI_THREADID " (main is %" PRI_THREADID ")", GetCurrentThreadId(), gEnv->mMainThreadId);
     CryLogAlways("CSystem::Quit invoked from thread %" PRI_THREADID " (main is %" PRI_THREADID ")", GetCurrentThreadId(), gEnv->mMainThreadId);
-    
+
     AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop);
     AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop);
 
 
     // If this was set from anywhere but the main thread, bail and let the main thread handle shutdown
     // If this was set from anywhere but the main thread, bail and let the main thread handle shutdown
@@ -857,13 +846,13 @@ void CSystem::Quit()
 
 
     /*
     /*
     * TODO: This call to _exit, _Exit, TerminateProcess etc. needs to
     * TODO: This call to _exit, _Exit, TerminateProcess etc. needs to
-    * eventually be removed. This causes an extremely early exit before we 
-    * actually perform cleanup. When this gets called most managers are 
+    * eventually be removed. This causes an extremely early exit before we
+    * actually perform cleanup. When this gets called most managers are
     * simply never deleted and we leave it to the OS to clean up our mess
     * simply never deleted and we leave it to the OS to clean up our mess
     * which is just really bad practice. However there are LOTS of issues
     * which is just really bad practice. However there are LOTS of issues
-    * with shutdown at the moment. Removing this will simply cause 
-    * a crash when either the Editor or Launcher initiate shutdown. Both 
-    * applications crash differently too. Bugs will be logged about those 
+    * with shutdown at the moment. Removing this will simply cause
+    * a crash when either the Editor or Launcher initiate shutdown. Both
+    * applications crash differently too. Bugs will be logged about those
     * issues.
     * issues.
     */
     */
 #if defined(AZ_RESTRICTED_PLATFORM)
 #if defined(AZ_RESTRICTED_PLATFORM)
@@ -1117,7 +1106,7 @@ void CSystem::CreatePhysicsThread()
 #include AZ_RESTRICTED_FILE(System_cpp)
 #include AZ_RESTRICTED_FILE(System_cpp)
 #endif
 #endif
 
 
-        {            
+        {
             m_PhysThread = new CPhysicsThreadTask;
             m_PhysThread = new CPhysicsThreadTask;
             GetIThreadTaskManager()->RegisterTask(m_PhysThread, threadParams);
             GetIThreadTaskManager()->RegisterTask(m_PhysThread, threadParams);
         }
         }
@@ -1412,7 +1401,7 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
         ti.xscale = ti.yscale = 1.2f;
         ti.xscale = ti.yscale = 1.2f;
 
 
         const int viewportHeight = GetViewCamera().GetViewSurfaceZ();
         const int viewportHeight = GetViewCamera().GetViewSurfaceZ();
-        
+
 #if defined(AZ_RESTRICTED_PLATFORM)
 #if defined(AZ_RESTRICTED_PLATFORM)
     #define AZ_RESTRICTED_SECTION SYSTEM_CPP_SECTION_8
     #define AZ_RESTRICTED_SECTION SYSTEM_CPP_SECTION_8
 #include AZ_RESTRICTED_FILE(System_cpp)
 #include AZ_RESTRICTED_FILE(System_cpp)
@@ -1428,7 +1417,7 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
             switch (stat.GetType())
             switch (stat.GetType())
             {
             {
             case AZ::IO::Statistic::Type::FloatingPoint:
             case AZ::IO::Statistic::Type::FloatingPoint:
-                gEnv->pRenderer->DrawTextQueued(Vec3(10, y, 1.0f), ti, 
+                gEnv->pRenderer->DrawTextQueued(Vec3(10, y, 1.0f), ti,
                     AZStd::string::format("%s/%s: %.3f", stat.GetOwner().data(), stat.GetName().data(), stat.GetFloatValue()).c_str());
                     AZStd::string::format("%s/%s: %.3f", stat.GetOwner().data(), stat.GetName().data(), stat.GetFloatValue()).c_str());
                 break;
                 break;
             case AZ::IO::Statistic::Type::Integer:
             case AZ::IO::Statistic::Type::Integer:
@@ -2744,10 +2733,10 @@ bool CSystem::HandleMessage([[maybe_unused]] HWND hWnd, UINT uMsg, WPARAM wParam
     {
     {
     // System event translation
     // System event translation
     case WM_CLOSE:
     case WM_CLOSE:
-        /* 
+        /*
             Trigger CSystem to call Quit() the next time
             Trigger CSystem to call Quit() the next time
             it calls Update(). HandleMessages can get messages
             it calls Update(). HandleMessages can get messages
-            pumped to it from SyncMainWithRender which would 
+            pumped to it from SyncMainWithRender which would
             be called recurively by Quit(). Doing so would
             be called recurively by Quit(). Doing so would
             cause the render thread to deadlock and the main
             cause the render thread to deadlock and the main
             thread to spin in SRenderThread::WaitFlushFinishedCond.
             thread to spin in SRenderThread::WaitFlushFinishedCond.
@@ -2897,11 +2886,6 @@ std::shared_ptr<AZ::IO::FileIOBase> CSystem::CreateLocalFileIO()
     return std::make_shared<AZ::IO::LocalFileIO>();
     return std::make_shared<AZ::IO::LocalFileIO>();
 }
 }
 
 
-const char* CSystem::GetAssetsPlatform() const
-{
-    return m_assetPlatform.c_str();
-}
-
 IViewSystem* CSystem::GetIViewSystem()
 IViewSystem* CSystem::GetIViewSystem()
 {
 {
     return m_pViewSystem;
     return m_pViewSystem;

+ 3 - 33
Code/CryEngine/CrySystem/System.h

@@ -45,7 +45,6 @@ struct IConsoleCmdArgs;
 class CServerThrottle;
 class CServerThrottle;
 struct ICryFactoryRegistryImpl;
 struct ICryFactoryRegistryImpl;
 struct IZLibCompressor;
 struct IZLibCompressor;
-class CLoadingProfilerSystem;
 class CWatchdogThread;
 class CWatchdogThread;
 class CThreadManager;
 class CThreadManager;
 
 
@@ -437,11 +436,6 @@ public:
 
 
     uint32 GetUsedMemory();
     uint32 GetUsedMemory();
 
 
-    //! For asset processor, we need to know what kind of assets we're loading.  This comes all the way from bootstrap.cfg
-    //! It will be a string like "pc" or "es3" or such and controls what kind of assets we have access to (its used when for example
-    //! attempting to open a file when multiple different assets for different platforms are available.)
-    const char* GetAssetsPlatform() const;
-
     virtual void DumpMemoryUsageStatistics(bool bUseKB);
     virtual void DumpMemoryUsageStatistics(bool bUseKB);
     virtual void DumpMemoryCoverage();
     virtual void DumpMemoryCoverage();
     void CollectMemInfo(SCryEngineStatsGlobalMemInfo&);
     void CollectMemInfo(SCryEngineStatsGlobalMemInfo&);
@@ -685,7 +679,7 @@ private:
     bool InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInitParams& initParams);
     bool InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInitParams& initParams);
 
 
     bool InitFont(const SSystemInitParams& initParams);
     bool InitFont(const SSystemInitParams& initParams);
-    bool InitFileSystem(const SSystemInitParams& initParams);
+    bool InitFileSystem();
     bool InitFileSystem_LoadEngineFolders(const SSystemInitParams& initParams);
     bool InitFileSystem_LoadEngineFolders(const SSystemInitParams& initParams);
     bool InitStreamEngine();
     bool InitStreamEngine();
     bool Init3DEngine(const SSystemInitParams& initParams);
     bool Init3DEngine(const SSystemInitParams& initParams);
@@ -792,7 +786,7 @@ public:
 
 
     const CTimeValue& GetLastTickTime(void) const { return m_lastTickTime; }
     const CTimeValue& GetLastTickTime(void) const { return m_lastTickTime; }
     const ICVar* GetDedicatedMaxRate(void) const { return m_svDedicatedMaxRate; }
     const ICVar* GetDedicatedMaxRate(void) const { return m_svDedicatedMaxRate; }
-   
+
     const char* GetRenderingDriverName(void) const
     const char* GetRenderingDriverName(void) const
     {
     {
         if(m_rDriver)
         if(m_rDriver)
@@ -802,7 +796,7 @@ public:
         return nullptr;
         return nullptr;
     }
     }
 
 
-    
+
     std::shared_ptr<AZ::IO::FileIOBase> CreateLocalFileIO();
     std::shared_ptr<AZ::IO::FileIOBase> CreateLocalFileIO();
 
 
     // Gets the dimensions (in pixels) of the primary physical display.
     // Gets the dimensions (in pixels) of the primary physical display.
@@ -914,7 +908,6 @@ private: // ------------------------------------------------------
 
 
     // DLL names
     // DLL names
     ICVar* m_sys_dll_response_system;
     ICVar* m_sys_dll_response_system;
-    ICVar* m_sys_game_folder;
 #if !defined(_RELEASE)
 #if !defined(_RELEASE)
     ICVar* m_sys_resource_cache_folder;
     ICVar* m_sys_resource_cache_folder;
 #endif
 #endif
@@ -950,7 +943,6 @@ private: // ------------------------------------------------------
     ICVar* m_rFullscreenWindow;
     ICVar* m_rFullscreenWindow;
     ICVar* m_rFullscreenNativeRes;
     ICVar* m_rFullscreenNativeRes;
     ICVar* m_rDriver;
     ICVar* m_rDriver;
-    ICVar* m_cvGameName;
     ICVar* m_rDisplayInfo;
     ICVar* m_rDisplayInfo;
     ICVar* m_rOverscanBordersDrawDebugView;
     ICVar* m_rOverscanBordersDrawDebugView;
     ICVar* m_sysNoUpdate;
     ICVar* m_sysNoUpdate;
@@ -1040,8 +1032,6 @@ private: // ------------------------------------------------------
 
 
     uint64 m_nUpdateCounter;
     uint64 m_nUpdateCounter;
 
 
-    int sys_ProfileLevelLoading, sys_ProfileLevelLoadingDump;
-
     bool m_executedCommandLine = false;
     bool m_executedCommandLine = false;
 
 
     AZStd::unique_ptr<AzFramework::MissingAssetLogger> m_missingAssetLogger;
     AZStd::unique_ptr<AzFramework::MissingAssetLogger> m_missingAssetLogger;
@@ -1072,18 +1062,6 @@ public:
     void CloseLanguageAudioPak(const char* sLanguage);
     void CloseLanguageAudioPak(const char* sLanguage);
     void UpdateMovieSystem(const int updateFlags, const float fFrameTime, const bool bPreUpdate);
     void UpdateMovieSystem(const int updateFlags, const float fFrameTime, const bool bPreUpdate);
 
 
-    // level loading profiling
-    virtual void OutputLoadingTimeStats();
-    virtual struct SLoadingTimeContainer* StartLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler, const char* szFuncName);
-    virtual void EndLoadingSectionProfiling(CLoadingTimeProfiler* pProfiler);
-    virtual const char* GetLoadingProfilerCallstack();
-
-    //////////////////////////////////////////////////////////////////////////
-    virtual CBootProfilerRecord* StartBootSectionProfiler(const char* name, const char* args);
-    virtual void StopBootSectionProfiler(CBootProfilerRecord* record);
-    virtual void StartBootProfilerSessionFrames(const char* pName);
-    virtual void StopBootProfilerSessionFrames();
-
     //////////////////////////////////////////////////////////////////////////
     //////////////////////////////////////////////////////////////////////////
     // CryAssert and error related.
     // CryAssert and error related.
     virtual bool RegisterErrorObserver(IErrorObserver* errorObserver);
     virtual bool RegisterErrorObserver(IErrorObserver* errorObserver);
@@ -1139,17 +1117,9 @@ protected: // -------------------------------------------------------------
     ITextModeConsole*             m_pTextModeConsole;
     ITextModeConsole*             m_pTextModeConsole;
     INotificationNetwork* m_pNotificationNetwork;
     INotificationNetwork* m_pNotificationNetwork;
 
 
-    string  m_binariesDir;
     string  m_currentLanguageAudio;
     string  m_currentLanguageAudio;
-    string  m_assetPlatform; // ("es3" / "pc" / etc) describes the KIND of assets we load and controls where they're loaded from
     string  m_systemConfigName; // computed from system_(hardwareplatform)_(assetsPlatform) - eg, system_android_es3.cfg or system_android_opengl.cfg or system_windows_pc.cfg
     string  m_systemConfigName; // computed from system_(hardwareplatform)_(assetsPlatform) - eg, system_android_es3.cfg or system_android_opengl.cfg or system_windows_pc.cfg
 
 
-    // the following variables capture what was set up in the systeminitparams after/during InitFileSystem
-    // They are not actually to be used except to establish aliases like @user@
-    string m_userRootDir;
-    string m_cacheDir;
-    string m_logsDir;
-
     std::vector< std::pair<CTimeValue, float> > m_updateTimes;
     std::vector< std::pair<CTimeValue, float> > m_updateTimes;
 
 
     CMemoryFragmentationProfiler    m_MemoryFragmentationProfiler;
     CMemoryFragmentationProfiler    m_MemoryFragmentationProfiler;

+ 3 - 9
Code/CryEngine/CrySystem/SystemCFG.cpp

@@ -23,6 +23,7 @@
 
 
 #include <AzCore/Console/IConsole.h>
 #include <AzCore/Console/IConsole.h>
 #include <AzCore/Interface/Interface.h>
 #include <AzCore/Interface/Interface.h>
+#include <AzCore/Utils/Utils.h>
 #include <AzFramework/StringFunc/StringFunc.h>
 #include <AzFramework/StringFunc/StringFunc.h>
 
 
 #include "SystemCFG.h"
 #include "SystemCFG.h"
@@ -252,15 +253,8 @@ void CSystem::LogVersion()
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 void CSystem::LogBuildInfo()
 void CSystem::LogBuildInfo()
 {
 {
-    ICVar* pGameName = m_env.pConsole->GetCVar("sys_game_name");
-    if (pGameName)
-    {
-        CryLogAlways("GameName: %s", pGameName->GetString());
-    }
-    else
-    {
-        CryLogAlways("Couldn't find game name in cvar sys_game_name");
-    }
+    auto projectName = AZ::Utils::GetProjectName();
+    CryLogAlways("GameName: %s", projectName.c_str());
     CryLogAlways("BuildTime: " __DATE__ " " __TIME__);
     CryLogAlways("BuildTime: " __DATE__ " " __TIME__);
 }
 }
 
 

+ 44 - 297
Code/CryEngine/CrySystem/SystemInit.cpp

@@ -68,6 +68,7 @@
 #include <LoadScreenBus.h>
 #include <LoadScreenBus.h>
 #include <LyShine/Bus/UiSystemBus.h>
 #include <LyShine/Bus/UiSystemBus.h>
 #include <AzFramework/Logging/MissingAssetLogger.h>
 #include <AzFramework/Logging/MissingAssetLogger.h>
+#include <AzFramework/Platform/PlatformDefaults.h>
 #include <AzFramework/API/AtomActiveInterface.h>
 #include <AzFramework/API/AtomActiveInterface.h>
 #include <AzCore/Interface/Interface.h>
 #include <AzCore/Interface/Interface.h>
 #include <AzCore/Utils/Utils.h>
 #include <AzCore/Utils/Utils.h>
@@ -115,8 +116,6 @@
 #include "SystemCFG.h"
 #include "SystemCFG.h"
 #include "AutoDetectSpec.h"
 #include "AutoDetectSpec.h"
 #include "ResourceManager.h"
 #include "ResourceManager.h"
-#include "LoadingProfiler.h"
-#include "BootProfiler.h"
 #include "VisRegTest.h"
 #include "VisRegTest.h"
 #include "MTSafeAllocator.h"
 #include "MTSafeAllocator.h"
 #include "NotificationNetwork.h"
 #include "NotificationNetwork.h"
@@ -498,7 +497,7 @@ struct SysSpecOverrideSinkConsole
         else
         else
         {
         {
             // If the cvar doesn't exist, calling this function only saves the value in case it's registered later where
             // If the cvar doesn't exist, calling this function only saves the value in case it's registered later where
-            // at that point it will be set from the stored value. This is required because otherwise registering the 
+            // at that point it will be set from the stored value. This is required because otherwise registering the
             // cvar bypasses any callbacks and uses values directly from the cvar group files.
             // cvar bypasses any callbacks and uses values directly from the cvar group files.
             gEnv->pConsole->LoadConfigVar(szKey, szValue);
             gEnv->pConsole->LoadConfigVar(szKey, szValue);
         }
         }
@@ -618,13 +617,13 @@ static void LoadDetectedSpec(ICVar* pVar)
     if (gEnv->IsEditor())
     if (gEnv->IsEditor())
     {
     {
         ESystemConfigPlatform configPlatform = GetISystem()->GetConfigPlatform();
         ESystemConfigPlatform configPlatform = GetISystem()->GetConfigPlatform();
-        // Check if the config platform is set first. 
+        // Check if the config platform is set first.
         if (configPlatform != CONFIG_INVALID_PLATFORM)
         if (configPlatform != CONFIG_INVALID_PLATFORM)
         {
         {
             platform = configPlatform;
             platform = configPlatform;
         }
         }
     }
     }
-    
+
     AZStd::string configFile;
     AZStd::string configFile;
     GetSpecConfigFileToLoad(pVar, configFile, platform);
     GetSpecConfigFileToLoad(pVar, configFile, platform);
     if (configFile.length())
     if (configFile.length())
@@ -779,7 +778,7 @@ static void LoadDetectedSpec(ICVar* pVar)
             MobileSysInspect::GetSpecForGPUAndAPI(adapterDesc, apiver, gpuConfigFile);
             MobileSysInspect::GetSpecForGPUAndAPI(adapterDesc, apiver, gpuConfigFile);
             GetISystem()->LoadConfiguration(gpuConfigFile.c_str(), pSysSpecOverrideSinkConsole);
             GetISystem()->LoadConfiguration(gpuConfigFile.c_str(), pSysSpecOverrideSinkConsole);
         }
         }
-#endif        
+#endif
     }
     }
     if (bMultiGPUEnabled)
     if (bMultiGPUEnabled)
     {
     {
@@ -832,23 +831,7 @@ AZStd::unique_ptr<AZ::DynamicModuleHandle> CSystem::LoadDynamiclibrary(const cha
 {
 {
     AZStd::unique_ptr<AZ::DynamicModuleHandle> handle = AZ::DynamicModuleHandle::Create(dllName);
     AZStd::unique_ptr<AZ::DynamicModuleHandle> handle = AZ::DynamicModuleHandle::Create(dllName);
 
 
-    bool libraryLoaded = false;
-#ifdef WIN32
-    if (m_binariesDir.empty())
-    {
-        libraryLoaded = handle->Load(false);
-    }
-    else
-    {
-        char currentDirectory[1024];
-        AZ::Utils::GetExecutableDirectory(currentDirectory, AZ_ARRAY_SIZE(currentDirectory));
-        SetCurrentDirectory(m_binariesDir.c_str());
-        libraryLoaded = handle->Load(false);
-        SetCurrentDirectory(currentDirectory);
-    }
-#else
-    libraryLoaded = handle->Load(false);
-#endif
+    bool libraryLoaded = handle->Load(false);
     // We need to inject the environment first thing so that allocators are available immediately
     // We need to inject the environment first thing so that allocators are available immediately
     InjectEnvironmentFunction injectEnv = handle->GetFunction<InjectEnvironmentFunction>(INJECT_ENVIRONMENT_FUNCTION);
     InjectEnvironmentFunction injectEnv = handle->GetFunction<InjectEnvironmentFunction>(INJECT_ENVIRONMENT_FUNCTION);
     if (injectEnv)
     if (injectEnv)
@@ -974,7 +957,7 @@ bool CSystem::InitializeEngineModule(const char* dllName, const char* moduleClas
 #endif
 #endif
 #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
 #if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
 #undef AZ_RESTRICTED_SECTION_IMPLEMENTED
 #undef AZ_RESTRICTED_SECTION_IMPLEMENTED
-#else 
+#else
 
 
     dllfile.append(dllName);
     dllfile.append(dllName);
 
 
@@ -1007,7 +990,7 @@ bool CSystem::InitializeEngineModule(const char* dllName, const char* moduleClas
     if (CryCreateClassInstance(moduleClassName, pModule))
     if (CryCreateClassInstance(moduleClassName, pModule))
     {
     {
         bResult = pModule->Initialize(m_env, initParams);
         bResult = pModule->Initialize(m_env, initParams);
-        
+
         // After initializing the module, give it a chance to register any AZ console vars
         // After initializing the module, give it a chance to register any AZ console vars
         // declared within the module.
         // declared within the module.
         pModule->RegisterConsoleVars();
         pModule->RegisterConsoleVars();
@@ -1453,7 +1436,7 @@ bool CSystem::InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInit
 
 
             displayWidth *= scaleFactor;
             displayWidth *= scaleFactor;
             displayHeight *= scaleFactor;
             displayHeight *= scaleFactor;
-            
+
             const int maxWidth = m_rMaxWidth->GetIVal();
             const int maxWidth = m_rMaxWidth->GetIVal();
             if (maxWidth > 0 && maxWidth < displayWidth)
             if (maxWidth > 0 && maxWidth < displayWidth)
             {
             {
@@ -1524,7 +1507,7 @@ bool CSystem::InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInit
 
 
 
 
 /////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////
-bool CSystem::InitFileSystem(const SSystemInitParams& initParams)
+bool CSystem::InitFileSystem()
 {
 {
     LOADING_TIME_PROFILE_SECTION;
     LOADING_TIME_PROFILE_SECTION;
     using namespace AzFramework::AssetSystem;
     using namespace AzFramework::AssetSystem;
@@ -1549,136 +1532,6 @@ bool CSystem::InitFileSystem(const SSystemInitParams& initParams)
     }
     }
 #endif // !defined(_RELEASE)
 #endif // !defined(_RELEASE)
 
 
-    bool usingAssetCache = initParams.UseAssetCache();
-    const char* rootPath = usingAssetCache ? initParams.rootPathCache : initParams.rootPath;
-    const char* assetsPath = usingAssetCache ? initParams.assetsPathCache : initParams.assetsPath;
-
-    if (rootPath == 0)
-    {
-        AZ_Assert(false, "No root path specified in SystemInitParams");
-        return false;
-    }
-
-    if (assetsPath == 0)
-    {
-        AZ_Assert(false, "No assets path specified in SystemInitParams");
-        return false;
-    }
-
-    // establish the root folder and assets folder immediately.
-    // Other folders that can be computed from the root can be specified later.
-    m_env.pFileIO->SetAlias("@root@", rootPath);
-    m_env.pFileIO->SetAlias("@assets@", assetsPath);
-
-    if (initParams.userPath[0] == 0)
-    {
-        string outPath = PathUtil::Make(m_env.pFileIO->GetAlias("@root@"), "user");
-        
-        m_env.pFileIO->SetAlias("@user@", outPath.c_str());
-    }
-    else
-    {
-        m_env.pFileIO->SetAlias("@user@", initParams.userPath);
-    }
-
-    if (initParams.logPath[0] == 0)
-    {
-        char resolveBuffer[AZ_MAX_PATH_LEN] = { 0 };
-
-        m_env.pFileIO->ResolvePath("@user@", resolveBuffer, AZ_MAX_PATH_LEN);
-        string outPath = PathUtil::Make(resolveBuffer, "log");
-        m_env.pFileIO->SetAlias("@log@", outPath.c_str());
-    }
-    else
-    {
-        m_env.pFileIO->SetAlias("@log@", initParams.logPath);
-    }
-
-    m_env.pFileIO->CreatePath("@root@");
-    m_env.pFileIO->CreatePath("@user@");
-    m_env.pFileIO->CreatePath("@log@");
-
-    if ((!m_env.IsInToolMode()) || (m_bShaderCacheGenMode)) // in tool mode, the promise is that you won't access @cache@!
-    {
-        string finalCachePath;
-        if (initParams.cachePath[0] == 0)
-        {
-            char resolveBuffer[AZ_MAX_PATH_LEN] = { 0 };
-
-            m_env.pFileIO->ResolvePath("@user@", resolveBuffer, AZ_MAX_PATH_LEN);
-            finalCachePath = PathUtil::Make(resolveBuffer, "cache");
-        }
-        else
-        {
-            finalCachePath = initParams.cachePath;
-        }
-
-#if defined(AZ_PLATFORM_WINDOWS)
-        // Search for a non-locked cache directory because shaders require separate caches for each running instance.
-        // We only need to do this check for Windows, because consoles can't have multiple instances running simultaneously.
-        // Ex: running editor and game, running multiple games, or multiple non-interactive editor instances 
-        // for parallel level exports.  
-
-        string originalPath = finalCachePath;
-#if defined(REMOTE_ASSET_PROCESSOR)
-        bool allowEngineConnection = !initParams.bToolMode && !initParams.bTestMode;
-        bool allowRemoteIO = allowEngineConnection && initParams.remoteFileIO && !initParams.bEditor;
-
-        if (!allowRemoteIO) // not running on VFS
-#endif
-        {
-            int attemptNumber = 0;
-
-            // The number of max attempts ultimately dictates the number of Lumberyard instances that can run
-            // simultaneously.  This should be a reasonably high number so that it doesn't artificially limit
-            // the number of instances (ex: parallel level exports via multiple Editor runs).  It also shouldn't 
-            // be set *infinitely* high - each cache folder is GBs in size, and finding a free directory is a 
-            // linear search, so the more instances we allow, the longer the search will take.  
-            // 128 seems like a reasonable compromise.
-            constexpr int maxAttempts = 128;
-
-            char workBuffer[AZ_MAX_PATH_LEN] = { 0 };
-            while (attemptNumber < maxAttempts)
-            {
-                finalCachePath = originalPath;
-                if (attemptNumber != 0)
-                {
-                    azsnprintf(workBuffer, AZ_MAX_PATH_LEN, "%s%i", originalPath.c_str(), attemptNumber);
-                    finalCachePath = workBuffer;
-                }
-                else
-                {
-                    finalCachePath = originalPath;
-                }
-
-                ++attemptNumber; // do this here so we don't forget
-
-                m_env.pFileIO->CreatePath(finalCachePath.c_str());
-                // if the directory already exists, check for locked file
-                string outLockPath = PathUtil::Make(finalCachePath.c_str(), "lockfile.txt");
-
-                // note, the zero here after GENERIC_READ|GENERIC_WRITE indicates no share access at all
-                g_cacheLock = CreateFileA(outLockPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, 0);
-                if (g_cacheLock != INVALID_HANDLE_VALUE)
-                {
-                    break;
-                }
-            }
-
-            if (attemptNumber >= maxAttempts)
-            {
-                AZ_Assert(false, "Couldn't find a valid asset cache folder for the Asset Processor after %i attempts.", attemptNumber);
-                AZ_Printf("FileSystem", "Couldn't find a valid asset cache folder for the Asset Processor after %i attempts.", attemptNumber);
-                return false;
-            }
-        }
-
-#endif // defined(AZ_PLATFORM_WINDOWS)
-        AZ_Printf("FileSystem", "Using %s folder for asset cache.\n", finalCachePath.c_str());
-        m_env.pFileIO->SetAlias("@cache@", finalCachePath.c_str());
-        m_env.pFileIO->CreatePath("@cache@");
-    }
-
     m_env.pCryPak = AZ::Interface<AZ::IO::IArchive>::Get();
     m_env.pCryPak = AZ::Interface<AZ::IO::IArchive>::Get();
     m_env.pFileIO = AZ::IO::FileIOBase::GetInstance();
     m_env.pFileIO = AZ::IO::FileIOBase::GetInstance();
     AZ_Assert(m_env.pCryPak, "CryPak has not been initialized on AZ::Interface");
     AZ_Assert(m_env.pCryPak, "CryPak has not been initialized on AZ::Interface");
@@ -1755,7 +1608,6 @@ void CSystem::ShutdownFileSystem()
 bool CSystem::InitFileSystem_LoadEngineFolders(const SSystemInitParams& initParams)
 bool CSystem::InitFileSystem_LoadEngineFolders(const SSystemInitParams& initParams)
 {
 {
     LOADING_TIME_PROFILE_SECTION;
     LOADING_TIME_PROFILE_SECTION;
-    // Load value of sys_game_folder from system.cfg into the sys_game_folder console variable
     {
     {
         ILoadConfigurationEntrySink* pCVarsWhiteListConfigSink = GetCVarsWhiteListConfigSink();
         ILoadConfigurationEntrySink* pCVarsWhiteListConfigSink = GetCVarsWhiteListConfigSink();
         LoadConfiguration(m_systemConfigName.c_str(), pCVarsWhiteListConfigSink);
         LoadConfiguration(m_systemConfigName.c_str(), pCVarsWhiteListConfigSink);
@@ -1767,17 +1619,19 @@ bool CSystem::InitFileSystem_LoadEngineFolders(const SSystemInitParams& initPara
 #endif
 #endif
 
 
     GetISystem()->SetConfigPlatform(GetDevicePlatform());
     GetISystem()->SetConfigPlatform(GetDevicePlatform());
-    
+
 #if defined(CRY_ENABLE_RC_HELPER)
 #if defined(CRY_ENABLE_RC_HELPER)
     if (!m_env.pResourceCompilerHelper)
     if (!m_env.pResourceCompilerHelper)
     {
     {
         m_env.pResourceCompilerHelper = new CResourceCompilerHelper();
         m_env.pResourceCompilerHelper = new CResourceCompilerHelper();
     }
     }
 #endif
 #endif
-    // you may not set these in game.cfg or in system.cfg
-    m_sys_game_folder->ForceSet(initParams.gameFolderName);
 
 
-    AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "GameDir: %s\n", m_sys_game_folder->GetString());
+    auto projectPath = AZ::Utils::GetProjectPath();
+    AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Project Path: %s\n", projectPath.empty() ? "None specified" : projectPath.c_str());
+
+    auto projectName = AZ::Utils::GetProjectName();
+    AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Project Name: %s\n", projectName.empty() ? "None specified" : projectName.c_str());
 
 
     // simply open all paks if fast load pak can't be found
     // simply open all paks if fast load pak can't be found
     if (!m_pResourceManager->LoadFastLoadPaks(true))
     if (!m_pResourceManager->LoadFastLoadPaks(true))
@@ -1857,7 +1711,7 @@ bool CSystem::InitFont(const SSystemInitParams& initParams)
 bool CSystem::Init3DEngine(const SSystemInitParams& initParams)
 bool CSystem::Init3DEngine(const SSystemInitParams& initParams)
 {
 {
     LOADING_TIME_PROFILE_SECTION(GetISystem());
     LOADING_TIME_PROFILE_SECTION(GetISystem());
-    
+
     if (!InitializeEngineModule(DLL_3DENGINE, "EngineModule_Cry3DEngine", initParams))
     if (!InitializeEngineModule(DLL_3DENGINE, "EngineModule_Cry3DEngine", initParams))
     {
     {
         return false;
         return false;
@@ -1930,7 +1784,7 @@ bool CSystem::InitVTuneProfiler()
     LOADING_TIME_PROFILE_SECTION(GetISystem());
     LOADING_TIME_PROFILE_SECTION(GetISystem());
 
 
 #ifdef PROFILE_WITH_VTUNE
 #ifdef PROFILE_WITH_VTUNE
-    
+
     WIN_HMODULE hModule = LoadDLL("VTuneApi.dll");
     WIN_HMODULE hModule = LoadDLL("VTuneApi.dll");
     if (!hModule)
     if (!hModule)
     {
     {
@@ -2033,7 +1887,7 @@ void CSystem::OpenBasicPaks()
     bBasicPaksLoaded = true;
     bBasicPaksLoaded = true;
 
 
     LOADING_TIME_PROFILE_SECTION;
     LOADING_TIME_PROFILE_SECTION;
-    
+
     // open pak files
     // open pak files
     constexpr AZStd::string_view paksFolder = "@assets@/*.pak"; // (@assets@ assumed)
     constexpr AZStd::string_view paksFolder = "@assets@/*.pak"; // (@assets@ assumed)
     m_env.pCryPak->OpenPacks(paksFolder);
     m_env.pCryPak->OpenPacks(paksFolder);
@@ -2188,12 +2042,6 @@ string GetUniqueLogFileName(string logFileName)
 }
 }
 
 
 
 
-
-void OnLevelLoadingDump([[maybe_unused]] ICVar* pArgs)
-{
-    gEnv->pSystem->OutputLoadingTimeStats();
-}
-
 #if defined(WIN32) || defined(WIN64)
 #if defined(WIN32) || defined(WIN64)
 static wstring GetErrorStringUnsupportedCPU()
 static wstring GetErrorStringUnsupportedCPU()
 {
 {
@@ -2415,8 +2263,8 @@ bool CSystem::Init(const SSystemInitParams& startupParams)
     signal(SIGILL, CryEngineSignalHandler);
     signal(SIGILL, CryEngineSignalHandler);
 #endif // AZ_TRAIT_USE_CRY_SIGNAL_HANDLER
 #endif // AZ_TRAIT_USE_CRY_SIGNAL_HANDLER
 
 
-    // Temporary Fix for an issue accessing gEnv from this object instance. The gEnv is not resolving to the 
-    // global gEnv, instead its resolving an some uninitialized gEnv elsewhere (NULL). Since gEnv is 
+    // Temporary Fix for an issue accessing gEnv from this object instance. The gEnv is not resolving to the
+    // global gEnv, instead its resolving an some uninitialized gEnv elsewhere (NULL). Since gEnv is
     // initialized to this instance's SSystemGlobalEnvironment (m_env), we will force set it again here
     // initialized to this instance's SSystemGlobalEnvironment (m_env), we will force set it again here
     // to m_env
     // to m_env
     if (!gEnv)
     if (!gEnv)
@@ -2451,7 +2299,7 @@ bool CSystem::Init(const SSystemInitParams& startupParams)
     // Linux is all console for now and so no room for dialog boxes!
     // Linux is all console for now and so no room for dialog boxes!
     m_env.bNoAssertDialog = true;
     m_env.bNoAssertDialog = true;
 #endif
 #endif
-    
+
     m_pCmdLine = new CCmdLine(startupParams.szSystemCmdLine);
     m_pCmdLine = new CCmdLine(startupParams.szSystemCmdLine);
 
 
     AZCoreLogSink::Connect();
     AZCoreLogSink::Connect();
@@ -2461,25 +2309,25 @@ bool CSystem::Init(const SSystemInitParams& startupParams)
     {
     {
         azConsole->LinkDeferredFunctors(AZ::ConsoleFunctorBase::GetDeferredHead());
         azConsole->LinkDeferredFunctors(AZ::ConsoleFunctorBase::GetDeferredHead());
     }
     }
-
-    m_assetPlatform = startupParams.assetsPlatform;
-
-    // compute system config name
-    if (m_assetPlatform.empty())
+    
+    if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry)
     {
     {
-        AZ_Error(AZ_TRACE_SYSTEM_WINDOW, false, R"(A valid asset platform is missing in "%s/assets" key in the SettingsRegistry.)""\n"
-            R"(This can be set via the via the --regset "%s/assets=<value>" command line option)"
-            R"(, by setting value at the "%s/assets path" within a *.setreg file that is loaded by the application)"
-            R"( or by setting the "assets" field in the bootstrap.cfg.)",
-            AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey,
-            AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey,
-            AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey);
-        return false;
-    }
+        AZ::SettingsRegistryInterface::FixedValueString assetPlatform;
+        if (!AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, assetPlatform,
+            AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey, "assets"))
+        {
+            assetPlatform = AzFramework::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
+            AZ_Warning(AZ_TRACE_SYSTEM_WINDOW, false, R"(A valid asset platform is missing in "%s/assets" key in the SettingsRegistry.)""\n"
+                R"(This typically done by setting he "assets" field in the bootstrap.cfg for within a .setreg file)""\n"
+                R"(A fallback of %s will be used.)",
+                AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey,
+                assetPlatform.c_str());
+        }
 
 
-    m_systemConfigName = "system_" AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER "_";
-    m_systemConfigName += m_assetPlatform;
-    m_systemConfigName += ".cfg";
+        m_systemConfigName = "system_" AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER "_";
+        m_systemConfigName += assetPlatform.c_str();
+        m_systemConfigName += ".cfg";
+    }
 
 
     AZ_Assert(CryMemory::IsHeapValid(), "Memory heap must be valid before continuing SystemInit.");
     AZ_Assert(CryMemory::IsHeapValid(), "Memory heap must be valid before continuing SystemInit.");
 
 
@@ -2518,11 +2366,6 @@ AZ_POP_DISABLE_WARNING
     m_hInst = (WIN_HINSTANCE)startupParams.hInstance;
     m_hInst = (WIN_HINSTANCE)startupParams.hInstance;
     m_hWnd = (WIN_HWND)startupParams.hWnd;
     m_hWnd = (WIN_HWND)startupParams.hWnd;
 
 
-    m_userRootDir = startupParams.userPath;
-    m_logsDir = startupParams.logPath;
-    m_cacheDir = startupParams.cachePath;
-
-    m_binariesDir = startupParams.szBinariesDir;
     m_bEditor = startupParams.bEditor;
     m_bEditor = startupParams.bEditor;
     m_bPreviewMode = startupParams.bPreview;
     m_bPreviewMode = startupParams.bPreview;
     m_bTestMode = startupParams.bTestMode;
     m_bTestMode = startupParams.bTestMode;
@@ -2666,17 +2509,13 @@ AZ_POP_DISABLE_WARNING
         //////////////////////////////////////////////////////////////////////////
         //////////////////////////////////////////////////////////////////////////
         // File system, must be very early
         // File system, must be very early
         //////////////////////////////////////////////////////////////////////////
         //////////////////////////////////////////////////////////////////////////
-        if (!InitFileSystem(startupParams))
+        if (!InitFileSystem())
         {
         {
             return false;
             return false;
         }
         }
         //////////////////////////////////////////////////////////////////////////
         //////////////////////////////////////////////////////////////////////////
         InlineInitializationProcessing("CSystem::Init InitFileSystem");
         InlineInitializationProcessing("CSystem::Init InitFileSystem");
 
 
-#if defined(ENABLE_LOADING_PROFILER)
-        CLoadingProfilerSystem::Init();
-#endif
-
         m_missingAssetLogger = AZStd::make_unique<AzFramework::MissingAssetLogger>();
         m_missingAssetLogger = AZStd::make_unique<AzFramework::MissingAssetLogger>();
 
 
         //////////////////////////////////////////////////////////////////////////
         //////////////////////////////////////////////////////////////////////////
@@ -2786,10 +2625,6 @@ AZ_POP_DISABLE_WARNING
 
 
         GetIRemoteConsole()->RegisterConsoleVariables();
         GetIRemoteConsole()->RegisterConsoleVariables();
 
 
-#ifdef ENABLE_LOADING_PROFILER
-        CBootProfiler::GetInstance().RegisterCVars();
-#endif
-
         if (!startupParams.bSkipConsole)
         if (!startupParams.bSkipConsole)
         {
         {
             // Register system console variables.
             // Register system console variables.
@@ -2827,7 +2662,7 @@ AZ_POP_DISABLE_WARNING
         m_env.pCryPak->OpenPack("@assets@", "Engine.pak");
         m_env.pCryPak->OpenPack("@assets@", "Engine.pak");
 #if defined(AZ_PLATFORM_ANDROID) || defined(AZ_PLATFORM_IOS)
 #if defined(AZ_PLATFORM_ANDROID) || defined(AZ_PLATFORM_IOS)
         MobileSysInspect::LoadDeviceSpecMapping();
         MobileSysInspect::LoadDeviceSpecMapping();
-#endif    
+#endif
 
 
         InitFileSystem_LoadEngineFolders(startupParams);
         InitFileSystem_LoadEngineFolders(startupParams);
 
 
@@ -3472,10 +3307,6 @@ AZ_POP_DISABLE_WARNING
         MarkThisThreadForDebugging("Main");
         MarkThisThreadForDebugging("Main");
     }
     }
 
 
-#if defined(ENABLE_LOADING_PROFILER)
-    CLoadingProfilerSystem::SaveTimeContainersToFile("EngineStart.crylp", 0.0, true);
-#endif
-
     InlineInitializationProcessing("CSystem::Init End");
     InlineInitializationProcessing("CSystem::Init End");
 
 
 #if defined(IS_PROSDK)
 #if defined(IS_PROSDK)
@@ -4188,7 +4019,7 @@ static void ScreenshotCmd(IConsoleCmdArgs* pParams)
     }
     }
 }
 }
 
 
-// Helper to maintain backwards compatibility with our CVar but not force our new code to 
+// Helper to maintain backwards compatibility with our CVar but not force our new code to
 // pull in CryCommon by routing through an environment variable
 // pull in CryCommon by routing through an environment variable
 void CmdSetAwsLogLevel(IConsoleCmdArgs* pArgs)
 void CmdSetAwsLogLevel(IConsoleCmdArgs* pArgs)
 {
 {
@@ -4424,7 +4255,6 @@ void CSystem::CreateSystemVars()
     // Register DLL names as cvars before we load them
     // Register DLL names as cvars before we load them
     //
     //
     EVarFlags dllFlags = (EVarFlags)0;
     EVarFlags dllFlags = (EVarFlags)0;
-    m_sys_game_folder = REGISTER_STRING("sys_game_folder", "EmptyTemplate", VF_READONLY,            "Specifies the game folder to read all data from. Can be fully pathed for external folders or relative path for folders inside the root.");
     m_sys_dll_response_system = REGISTER_STRING("sys_dll_response_system", 0, dllFlags,                 "Specifies the DLL to load for the dynamic response system");
     m_sys_dll_response_system = REGISTER_STRING("sys_dll_response_system", 0, dllFlags,                 "Specifies the DLL to load for the dynamic response system");
 
 
     m_sys_initpreloadpacks = REGISTER_STRING("sys_initpreloadpacks", "", 0,     "Specifies the paks for an engine initialization");
     m_sys_initpreloadpacks = REGISTER_STRING("sys_initpreloadpacks", "", 0,     "Specifies the paks for an engine initialization");
@@ -4447,8 +4277,6 @@ void CSystem::CreateSystemVars()
     m_level_load_screen_minimum_time = REGISTER_FLOAT("level_load_screen_minimum_time", 0.0f, 0, "Minimum amount of time to show the level load screen. Important to prevent short loads from flashing the load screen. 0 means there is no limit.");
     m_level_load_screen_minimum_time = REGISTER_FLOAT("level_load_screen_minimum_time", 0.0f, 0, "Minimum amount of time to show the level load screen. Important to prevent short loads from flashing the load screen. 0 means there is no limit.");
 #endif // if AZ_LOADSCREENCOMPONENT_ENABLED
 #endif // if AZ_LOADSCREENCOMPONENT_ENABLED
 
 
-    m_cvGameName = REGISTER_STRING("sys_game_name", "Lumberyard", VF_DUMPTODISK,    "Specifies the name to be displayed in the Launcher window title bar");
-
     REGISTER_INT("cvDoVerboseWindowTitle", 0, VF_NULL, "");
     REGISTER_INT("cvDoVerboseWindowTitle", 0, VF_NULL, "");
 
 
     m_pCVarQuit = REGISTER_INT("ExitOnQuit", 1, VF_NULL, "");
     m_pCVarQuit = REGISTER_INT("ExitOnQuit", 1, VF_NULL, "");
@@ -4495,7 +4323,7 @@ void CSystem::CreateSystemVars()
     }
     }
  #endif
  #endif
 
 
-    
+
     attachVariable("sys_PakReadSlice", &g_cvars.archiveVars.nReadSlice, "If non-0, means number of kilobytes to use to read files in portions. Should only be used on Win9x kernels");
     attachVariable("sys_PakReadSlice", &g_cvars.archiveVars.nReadSlice, "If non-0, means number of kilobytes to use to read files in portions. Should only be used on Win9x kernels");
 
 
     attachVariable("sys_PakInMemorySizeLimit", &g_cvars.archiveVars.nInMemoryPerPakSizeLimit, "Individual pak size limit for being loaded into memory (MB)");
     attachVariable("sys_PakInMemorySizeLimit", &g_cvars.archiveVars.nInMemoryPerPakSizeLimit, "Individual pak size limit for being loaded into memory (MB)");
@@ -4818,15 +4646,6 @@ void CSystem::CreateSystemVars()
         "e.g. LoadConfig lowspec.cfg\n"
         "e.g. LoadConfig lowspec.cfg\n"
         "Usage: LoadConfig <filename>");
         "Usage: LoadConfig <filename>");
 
 
-    REGISTER_CVAR(sys_ProfileLevelLoading, 0, VF_CHEAT,
-        "Output level loading stats into log\n"
-        "0 = Off\n"
-        "1 = Output basic info about loading time per function\n"
-        "2 = Output full statistics including loading time and memory allocations with call stack info");
-
-    REGISTER_CVAR_CB(sys_ProfileLevelLoadingDump, 0, VF_CHEAT,  "Output level loading dump stats into log\n", OnLevelLoadingDump);
-
-
     assert(m_env.pConsole);
     assert(m_env.pConsole);
     m_env.pConsole->CreateKeyBind("alt_keyboard_key_function_F12", "Screenshot");
     m_env.pConsole->CreateKeyBind("alt_keyboard_key_function_F12", "Screenshot");
     m_env.pConsole->CreateKeyBind("alt_keyboard_key_function_F11", "RecordClip");
     m_env.pConsole->CreateKeyBind("alt_keyboard_key_function_F11", "RecordClip");
@@ -4871,7 +4690,7 @@ void CSystem::CreateSystemVars()
 
 
     // adding CVAR to toggle assert verbosity level
     // adding CVAR to toggle assert verbosity level
     const int defaultAssertValue = 1;
     const int defaultAssertValue = 1;
-    REGISTER_CVAR2_CB("sys_asserts", &g_cvars.sys_asserts, defaultAssertValue, VF_CHEAT, 
+    REGISTER_CVAR2_CB("sys_asserts", &g_cvars.sys_asserts, defaultAssertValue, VF_CHEAT,
         "0 = Suppress Asserts\n"
         "0 = Suppress Asserts\n"
         "1 = Log Asserts\n"
         "1 = Log Asserts\n"
         "2 = Show Assert Dialog\n"
         "2 = Show Assert Dialog\n"
@@ -4957,78 +4776,6 @@ void CSystem::AddCVarGroupDirectory(const string& sPath)
     gEnv->pCryPak->FindClose(handle);
     gEnv->pCryPak->FindClose(handle);
 }
 }
 
 
-void CSystem::OutputLoadingTimeStats()
-{
-#if defined(ENABLE_LOADING_PROFILER)
-    if (GetIConsole())
-    {
-        if (ICVar* pVar = GetIConsole()->GetCVar("sys_ProfileLevelLoading"))
-        {
-            CLoadingProfilerSystem::OutputLoadingTimeStats(GetILog(), pVar->GetIVal());
-        }
-    }
-#endif
-}
-
-SLoadingTimeContainer* CSystem::StartLoadingSectionProfiling([[maybe_unused]] CLoadingTimeProfiler* pProfiler, [[maybe_unused]] const char* szFuncName)
-{
-#if defined(ENABLE_LOADING_PROFILER)
-    return CLoadingProfilerSystem::StartLoadingSectionProfiling(pProfiler, szFuncName);
-#else
-    return 0;
-#endif
-}
-
-void CSystem::EndLoadingSectionProfiling([[maybe_unused]] CLoadingTimeProfiler* pProfiler)
-{
-#if defined(ENABLE_LOADING_PROFILER)
-    CLoadingProfilerSystem::EndLoadingSectionProfiling(pProfiler);
-#endif
-}
-
-const char* CSystem::GetLoadingProfilerCallstack()
-{
-#if defined(ENABLE_LOADING_PROFILER)
-    return CLoadingProfilerSystem::GetLoadingProfilerCallstack();
-#else
-    return nullptr;
-#endif
-}
-
-CBootProfilerRecord* CSystem::StartBootSectionProfiler([[maybe_unused]] const char* name, [[maybe_unused]] const char* args)
-{
-#if defined(ENABLE_LOADING_PROFILER)
-    CBootProfiler& profiler = CBootProfiler::GetInstance();
-    return profiler.StartBlock(name, args);
-#else
-    return nullptr;
-#endif
-}
-
-void CSystem::StopBootSectionProfiler([[maybe_unused]] CBootProfilerRecord* record)
-{
-#if defined(ENABLE_LOADING_PROFILER)
-    CBootProfiler& profiler = CBootProfiler::GetInstance();
-    profiler.StopBlock(record);
-#endif
-}
-
-void CSystem::StartBootProfilerSessionFrames([[maybe_unused]] const char* pName)
-{
-#if defined(ENABLE_LOADING_PROFILER)
-    CBootProfiler& profiler = CBootProfiler::GetInstance();
-    profiler.StartFrame(pName);
-#endif
-}
-
-void CSystem::StopBootProfilerSessionFrames()
-{
-#if defined(ENABLE_LOADING_PROFILER)
-    CBootProfiler& profiler = CBootProfiler::GetInstance();
-    profiler.StopFrame();
-#endif
-}
-
 bool CSystem::RegisterErrorObserver(IErrorObserver* errorObserver)
 bool CSystem::RegisterErrorObserver(IErrorObserver* errorObserver)
 {
 {
     return stl::push_back_unique(m_errorObservers, errorObserver);
     return stl::push_back_unique(m_errorObservers, errorObserver);

+ 0 - 15
Code/CryEngine/CrySystem/SystemWin32.cpp

@@ -92,13 +92,6 @@ static AZStd::vector<AZStd::string> GetModuleNames()
         moduleNames.push_back("CryFont" MODULE_EXTENSION);
         moduleNames.push_back("CryFont" MODULE_EXTENSION);
         moduleNames.push_back("CrySystem" MODULE_EXTENSION);
         moduleNames.push_back("CrySystem" MODULE_EXTENSION);
 
 
-        if (gEnv && gEnv->pConsole)
-        {
-            string gameModuleNameRaw = gEnv->pConsole->GetCVar("sys_dll_game")->GetString();
-            gameModuleNameRaw.append(MODULE_EXTENSION);
-            moduleNames.push_back(gameModuleNameRaw.c_str());
-        }
-
 #undef MODULE_EXTENSION
 #undef MODULE_EXTENSION
 
 
 #   if defined(LINUX)
 #   if defined(LINUX)
@@ -1076,14 +1069,6 @@ void CSystem::FatalError(const char* format, ...)
         CryLogAlways("<CrySystem> Last System Error: %s", szSysErrorMessage);
         CryLogAlways("<CrySystem> Last System Error: %s", szSysErrorMessage);
     }
     }
 
 
-    if (const char* pLoadingProfilerCallstack = GetLoadingProfilerCallstack())
-    {
-        if (pLoadingProfilerCallstack[0])
-        {
-            CryLogAlways("<CrySystem> LoadingProfilerCallstack: %s", pLoadingProfilerCallstack);
-        }
-    }
-
     if (GetUserCallback())
     if (GetUserCallback())
     {
     {
         GetUserCallback()->OnError(szBuffer);
         GetUserCallback()->OnError(szBuffer);

+ 0 - 115
Code/CryEngine/CrySystem/Tests/Test_BootProfiler.cpp

@@ -1,115 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-#include "CrySystem_precompiled.h"
-
-#include <AzTest/AzTest.h>
-#include <AzCore/UnitTest/UnitTest.h>
-#include <AzCore/UnitTest/TestTypes.h>
-#include <AzCore/Memory/AllocatorScope.h>
-#include <AzCore/std/string/string.h>
-#include <BootProfiler.h>
-
-#if defined(ENABLE_LOADING_PROFILER)
-
-namespace UnitTests
-{
-    using BootProfilerTestAllocatorScope = AZ::AllocatorScope<AZ::LegacyAllocator, CryStringAllocator>;
-    class BootProfilerTest :
-        public ::testing::Test,
-        BootProfilerTestAllocatorScope,
-        UnitTest::TraceBusRedirector
-    {
-    public:
-        BootProfilerTest()
-        {
-            BootProfilerTestAllocatorScope::ActivateAllocators();
-            UnitTest::TraceBusRedirector::BusConnect();
-        }
-
-        ~BootProfilerTest() 
-        {
-            UnitTest::TraceBusRedirector::BusDisconnect();
-            BootProfilerTestAllocatorScope::DeactivateAllocators();
-        }
-
-        void SetUp() override
-        {
-
-        }
-
-        void TearDown() override
-        {
-
-        }
-
-    };
-
-    TEST_F(BootProfilerTest, BootProfilerTest_StartStopBlocksInThreads_Success)
-    {
-        CBootProfiler testProfiler;
-        const char scopeName[] = "TestScope";
-        const char blockArg[] = "TestArg";
-        const int numAttempts = 1000;
-        const int numThreads = 10;
-
-        auto switchSessionFunc = [&]() {
-            for (int sessionNum = 0; sessionNum < numAttempts; ++sessionNum)
-            {
-                auto sessionName = AZStd::string::format("TestSession%d", sessionNum);
-                testProfiler.StartSession(sessionName.c_str());
-                testProfiler.StopSession(sessionName.c_str());
-            }
-        };
-        auto testProfileFunc = [&]() {
-            for (int blockNum = 0; blockNum < numAttempts; ++blockNum)
-            {
-                auto someBlock = testProfiler.StartBlock(scopeName, blockArg);
-                testProfiler.StopBlock(someBlock);
-            }
-        };
-        AZStd::thread threadArray[numThreads];
-
-        AZStd::thread sessionThread = AZStd::thread(switchSessionFunc);
-        for (int i = 0; i < numThreads; ++i)
-        {
-            threadArray[i] = AZStd::thread(testProfileFunc);
-        }
-        for (int i = 0; i < numThreads; ++i)
-        {
-            threadArray[i].join();
-        }
-        sessionThread.join();
-    }
-
-    class FrameTestBootProfiler : public CBootProfiler
-    {
-    public:
-        FrameTestBootProfiler(int frameCount) : CBootProfiler()
-        {
-            SetFrameCount(frameCount);
-        }
-    };
-    TEST_F(BootProfilerTest, BootProfilerTest_FrameStartStop_Success)
-    {
-        const int numTestFrames = 10;
-        FrameTestBootProfiler testProfiler(numTestFrames);
-
-        for (int i = 0; i < numTestFrames; ++i)
-        {
-            testProfiler.StartFrame("TestFrame");
-
-            testProfiler.StopFrame();
-        }
-    }
-} // namespace UnitTests
-
-#endif

+ 5 - 10
Code/CryEngine/CrySystem/Tests/test_MaterialUtils.cpp

@@ -75,15 +75,10 @@ TEST(CrySystemMaterialUtilsTests, MaterialUtilsTestPrefixes)
 TEST(CrySystemMaterialUtilsTests, MaterialUtilsTestGameName)
 TEST(CrySystemMaterialUtilsTests, MaterialUtilsTestGameName)
 {
 {
     char tempBuffer[AZ_MAX_PATH_LEN];
     char tempBuffer[AZ_MAX_PATH_LEN];
-    
-    ICVar* pGameNameCVar = nullptr;
-    if ((gEnv)&&(gEnv->pConsole))
-    {
-        pGameNameCVar = gEnv->pConsole->GetCVar("sys_game_folder");
-    }
-
-    azsnprintf(tempBuffer, AZ_MAX_PATH_LEN, ".\\%s\\materials\\blahblah.mat.mat.abc.test", pGameNameCVar ? pGameNameCVar->GetString() : "SamplesProject");
- 
+
+    auto projectName = AZ::Utils::GetProjectName();
+    azsnprintf(tempBuffer, AZ_MAX_PATH_LEN, ".\\%s\\materials\\blahblah.mat.mat.abc.test", projectName.c_str());
+
     MaterialUtils::UnifyMaterialName(tempBuffer);
     MaterialUtils::UnifyMaterialName(tempBuffer);
     EXPECT_TRUE(strcmp(tempBuffer, "materials/blahblah.mat.mat.abc") == 0);
     EXPECT_TRUE(strcmp(tempBuffer, "materials/blahblah.mat.mat.abc") == 0);
-}
+}

+ 2 - 2
Code/CryEngine/CrySystem/UnitTests/CryPakUnitTests.cpp

@@ -60,7 +60,7 @@ namespace CryPakUnitTests
         AZ::IO::FileIOBase* fileIo = AZ::IO::FileIOBase::GetInstance();
         AZ::IO::FileIOBase* fileIo = AZ::IO::FileIOBase::GetInstance();
         ASSERT_NE(nullptr, fileIo);
         ASSERT_NE(nullptr, fileIo);
 
 
-        constexpr const char* testPakPath = "@cache@/archivecontainerlevel.pak";
+        constexpr const char* testPakPath = "@usercache@/archivecontainerlevel.pak";
 
 
         char resolvedArchivePath[AZ_MAX_PATH_LEN] = { 0 };
         char resolvedArchivePath[AZ_MAX_PATH_LEN] = { 0 };
         EXPECT_TRUE(fileIo->ResolvePath(testPakPath, resolvedArchivePath, AZ_MAX_PATH_LEN));
         EXPECT_TRUE(fileIo->ResolvePath(testPakPath, resolvedArchivePath, AZ_MAX_PATH_LEN));
@@ -116,7 +116,7 @@ namespace CryPakUnitTests
             AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds{ 100 });
             AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds{ 100 });
 
 
             // helper paths and strings
             // helper paths and strings
-            AZStd::string gameFolder = fileIo->GetAlias("@cache@");
+            AZStd::string gameFolder = fileIo->GetAlias("@usercache@");
 
 
             AZStd::string testFile = "unittest.bin";
             AZStd::string testFile = "unittest.bin";
             AZStd::string testFilePath = gameFolder + "\\" + testFile;
             AZStd::string testFilePath = gameFolder + "\\" + testFile;

+ 2 - 2
Code/CryEngine/CrySystem/VisRegTest.cpp

@@ -297,7 +297,7 @@ void CVisRegTest::CaptureSample(const SCmd& cmd)
     if (m_cmdFreq == 1)   // Final sample
     if (m_cmdFreq == 1)   // Final sample
     {
     {
         // Screenshot
         // Screenshot
-        stack_string filename("@cache@/TestResults/VisReg/");   // the default unaliased assets folder is read-only!
+        stack_string filename("@usercache@/TestResults/VisReg/");   // the default unaliased assets folder is read-only!
         filename += m_testName + "/" + cmd.args.c_str();
         filename += m_testName + "/" + cmd.args.c_str();
         gEnv->pRenderer->ScreenShot(filename);
         gEnv->pRenderer->ScreenShot(filename);
 
 
@@ -335,7 +335,7 @@ void CVisRegTest::Finish()
 
 
 bool CVisRegTest::WriteResults()
 bool CVisRegTest::WriteResults()
 {
 {
-    stack_string filename("@cache@/TestResults/VisReg/");
+    stack_string filename("@usercache@/TestResults/VisReg/");
     filename += m_testName + "/visreg_results.xml";
     filename += m_testName + "/visreg_results.xml";
 
 
     AZ::IO::HandleType fileHandle = fxopen(filename.c_str(), "wb");
     AZ::IO::HandleType fileHandle = fxopen(filename.c_str(), "wb");

+ 0 - 4
Code/CryEngine/CrySystem/crysystem_files.cmake

@@ -26,7 +26,6 @@ set(FILES
     IDebugCallStack.cpp
     IDebugCallStack.cpp
     AsyncPakManager.cpp
     AsyncPakManager.cpp
     Log.cpp
     Log.cpp
-    BootProfiler.cpp
     SystemRender.cpp
     SystemRender.cpp
     NotificationNetwork.cpp
     NotificationNetwork.cpp
     PhysRenderer.cpp
     PhysRenderer.cpp
@@ -91,7 +90,6 @@ set(FILES
     WindowsConsole.h
     WindowsConsole.h
     XConsole.h
     XConsole.h
     XConsoleVariable.h
     XConsoleVariable.h
-    BootProfiler.h
     crash_face.bmp
     crash_face.bmp
     ImageHandler.h
     ImageHandler.h
     ImageHandler.cpp
     ImageHandler.cpp
@@ -121,11 +119,9 @@ set(FILES
     XML/WriteXMLSource.cpp
     XML/WriteXMLSource.cpp
     ZipFile.h
     ZipFile.h
     ZipFileFormat_info.h
     ZipFileFormat_info.h
-    LoadingProfiler.cpp
     PerfHUD.cpp
     PerfHUD.cpp
     ProfileLogSystem.cpp
     ProfileLogSystem.cpp
     Sampler.cpp
     Sampler.cpp
-    LoadingProfiler.h
     PerfHUD.h
     PerfHUD.h
     ProfileLogSystem.h
     ProfileLogSystem.h
     Sampler.h
     Sampler.h

+ 2 - 2
Code/CryEngine/RenderDll/Common/Renderer.cpp

@@ -902,7 +902,7 @@ void ShadersOptimizeHelper(CallableT setupParserBin, const char* logString)
 {
 {
     setupParserBin();
     setupParserBin();
     CryLogAlways("\nStarting shaders optimizing for %s...", logString);
     CryLogAlways("\nStarting shaders optimizing for %s...", logString);
-    AZStd::string str = "@cache@/" + gRenDev->m_cEF.m_ShadersCache;
+    AZStd::string str = "@usercache@/" + gRenDev->m_cEF.m_ShadersCache;
     iLog->Log("Optimize shader cache folder: '%s'", gRenDev->m_cEF.m_ShadersCache.c_str());
     iLog->Log("Optimize shader cache folder: '%s'", gRenDev->m_cEF.m_ShadersCache.c_str());
     gRenDev->m_cEF.mfOptimiseShaders(str.c_str(), false);
     gRenDev->m_cEF.mfOptimiseShaders(str.c_str(), false);
 }
 }
@@ -2396,7 +2396,7 @@ void CRenderer::InitRenderer()
 
 
     CV_r_ShaderCompilerFolderSuffix = REGISTER_STRING("r_ShaderCompilerFolderSuffix", "", VF_NULL,
     CV_r_ShaderCompilerFolderSuffix = REGISTER_STRING("r_ShaderCompilerFolderSuffix", "", VF_NULL,
             "Usage: r_ShaderCompilerFolderSuffix suffix \n"
             "Usage: r_ShaderCompilerFolderSuffix suffix \n"
-            "Default is empty. Set to some other value to append this suffix to the sys_game_folder when compiling shaders");
+            "Default is empty. Set to some other value to append this suffix to the project name when compiling shaders");
 
 
     {
     {
         const SFileVersion& ver = gEnv->pSystem->GetFileVersion();
         const SFileVersion& ver = gEnv->pSystem->GetFileVersion();

+ 10 - 12
Code/CryEngine/RenderDll/Common/Shaders/RemoteCompiler.cpp

@@ -20,6 +20,7 @@
 #include <AzCore/Socket/AzSocket.h>
 #include <AzCore/Socket/AzSocket.h>
 #include <AzCore/NativeUI/NativeUIRequests.h>
 #include <AzCore/NativeUI/NativeUIRequests.h>
 #include <AzCore/PlatformId/PlatformId.h>
 #include <AzCore/PlatformId/PlatformId.h>
+#include <AzCore/Utils/Utils.h>
 #include <AzFramework/Network/SocketConnection.h>
 #include <AzFramework/Network/SocketConnection.h>
 #include <AzFramework/Asset/AssetSystemTypes.h>
 #include <AzFramework/Asset/AssetSystemTypes.h>
 
 
@@ -306,23 +307,20 @@ namespace NRemoteCompiler
 
 
         m_RequestLineRootFolder = "";
         m_RequestLineRootFolder = "";
 
 
-        ICVar* pGameFolder = gEnv->pConsole->GetCVar("sys_game_folder");
+        auto projectName = AZ::Utils::GetProjectName();
         ICVar* pCompilerFolderSuffix = CRenderer::CV_r_ShaderCompilerFolderSuffix;
         ICVar* pCompilerFolderSuffix = CRenderer::CV_r_ShaderCompilerFolderSuffix;
 
 
-        if (pGameFolder)
+        if (!projectName.empty())
         {
         {
-            string folder = pGameFolder->GetString();
-            folder.Trim();
-            if (!folder.empty())
+            if (pCompilerFolderSuffix)
             {
             {
-                if (pCompilerFolderSuffix)
-                {
-                    string suffix = pCompilerFolderSuffix->GetString();
-                    suffix.Trim();
-                    folder.append(suffix);
-                }
-                m_RequestLineRootFolder = folder + string("/");
+                string suffix = pCompilerFolderSuffix->GetString();
+                suffix.Trim();
+                projectName.append(suffix);
             }
             }
+
+            projectName.append("/");
+            m_RequestLineRootFolder.assign(projectName.c_str(), projectName.size());
         }
         }
 
 
         if (m_RequestLineRootFolder.empty())
         if (m_RequestLineRootFolder.empty())

+ 99 - 32
Code/CryEngine/RenderDll/Common/Shaders/RemoteShaderCompilerUnitTests.cpp

@@ -13,16 +13,61 @@
 #include <AzTest/AzTest.h>
 #include <AzTest/AzTest.h>
 #include <AzCore/UnitTest/TestTypes.h>
 #include <AzCore/UnitTest/TestTypes.h>
 #include <AzCore/Memory/AllocatorScope.h>
 #include <AzCore/Memory/AllocatorScope.h>
+#include <AzCore/Settings/SettingsRegistry.h>
 #include <AzCore/UnitTest/UnitTest.h>
 #include <AzCore/UnitTest/UnitTest.h>
 #include "Mocks/IConsoleMock.h"
 #include "Mocks/IConsoleMock.h"
 #include "Mocks/ICVarMock.h"
 #include "Mocks/ICVarMock.h"
 #include "Mocks/ISystemMock.h"
 #include "Mocks/ISystemMock.h"
 #include "RemoteCompiler.h"
 #include "RemoteCompiler.h"
 
 
+
+namespace AZ
+{
+    class SettingsRegistrySimpleMock;
+    using NiceSettingsRegistrySimpleMock = ::testing::NiceMock<SettingsRegistrySimpleMock>;
+
+    class SettingsRegistrySimpleMock : public AZ::SettingsRegistryInterface
+    {
+    public:
+        MOCK_CONST_METHOD1(GetType, Type(AZStd::string_view));
+        MOCK_CONST_METHOD2(Visit, bool(Visitor&, AZStd::string_view));
+        MOCK_CONST_METHOD2(Visit, bool(const VisitorCallback&, AZStd::string_view));
+        MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(const NotifyCallback&));
+        MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(NotifyCallback&&));
+
+        MOCK_CONST_METHOD2(Get, bool(bool&, AZStd::string_view));
+        MOCK_CONST_METHOD2(Get, bool(s64&, AZStd::string_view));
+        MOCK_CONST_METHOD2(Get, bool(u64&, AZStd::string_view));
+        MOCK_CONST_METHOD2(Get, bool(double&, AZStd::string_view));
+        MOCK_CONST_METHOD2(Get, bool(AZStd::string&, AZStd::string_view));
+        MOCK_CONST_METHOD2(Get, bool(FixedValueString&, AZStd::string_view));
+        MOCK_CONST_METHOD3(GetObject, bool(void*, Uuid, AZStd::string_view));
+
+        MOCK_METHOD2(Set, bool(AZStd::string_view, bool));
+        MOCK_METHOD2(Set, bool(AZStd::string_view, s64));
+        MOCK_METHOD2(Set, bool(AZStd::string_view, u64));
+        MOCK_METHOD2(Set, bool(AZStd::string_view, double));
+        MOCK_METHOD2(Set, bool(AZStd::string_view, AZStd::string_view));
+        MOCK_METHOD2(Set, bool(AZStd::string_view, const char*));
+        MOCK_METHOD3(SetObject, bool(AZStd::string_view, const void*, Uuid));
+
+        MOCK_METHOD1(Remove, bool(AZStd::string_view));
+
+        MOCK_METHOD3(MergeCommandLineArgument, bool(AZStd::string_view, AZStd::string_view, const CommandLineArgumentSettings&));
+        MOCK_METHOD2(MergeSettings, bool(AZStd::string_view, Format));
+        MOCK_METHOD4(MergeSettingsFile, bool(AZStd::string_view, Format, AZStd::string_view, AZStd::vector<char>*));
+        MOCK_METHOD5(
+            MergeSettingsFolder,
+            bool(AZStd::string_view, const Specializations&, AZStd::string_view, AZStd::string_view, AZStd::vector<char>*));
+    };
+} // namespace AZ
+
+
 namespace NRemoteCompiler
 namespace NRemoteCompiler
 {
 {
     using ::testing::NiceMock;
     using ::testing::NiceMock;
     using ::testing::Return;
     using ::testing::Return;
+    using ::testing::DoAll;
 
 
     using SystemAllocatorScope = AZ::AllocatorScope<AZ::LegacyAllocator, CryStringAllocator>;
     using SystemAllocatorScope = AZ::AllocatorScope<AZ::LegacyAllocator, CryStringAllocator>;
 
 
@@ -65,9 +110,12 @@ namespace NRemoteCompiler
             SystemAllocatorScope::ActivateAllocators();
             SystemAllocatorScope::ActivateAllocators();
 
 
             m_priorEnv = gEnv;
             m_priorEnv = gEnv;
+            m_priorSettingsRegistry = AZ::SettingsRegistry::Get();
 
 
             m_data.reset(new DataMembers);
             m_data.reset(new DataMembers);
 
 
+            AZ::SettingsRegistry::Register(&m_data->m_settings);
+
             ON_CALL(m_data->m_console, GetCVar(_))
             ON_CALL(m_data->m_console, GetCVar(_))
                 .WillByDefault(Return(&m_data->m_cvarMock));
                 .WillByDefault(Return(&m_data->m_cvarMock));
 
 
@@ -89,6 +137,11 @@ namespace NRemoteCompiler
         void TearDown() override
         void TearDown() override
         {
         {
             gEnv = m_priorEnv;
             gEnv = m_priorEnv;
+            AZ::SettingsRegistry::Unregister(&m_data->m_settings);
+            if (m_priorSettingsRegistry)
+            {
+                AZ::SettingsRegistry::Register(m_priorSettingsRegistry);
+            }
             m_data.reset();
             m_data.reset();
             SystemAllocatorScope::DeactivateAllocators();
             SystemAllocatorScope::DeactivateAllocators();
             AllocatorsTestFixture::TearDown();
             AllocatorsTestFixture::TearDown();
@@ -99,12 +152,14 @@ namespace NRemoteCompiler
             NiceMock<SystemMock> m_system;
             NiceMock<SystemMock> m_system;
             NiceMock<ConsoleMock> m_console;
             NiceMock<ConsoleMock> m_console;
             NiceMock<CVarMock> m_cvarMock;
             NiceMock<CVarMock> m_cvarMock;
+            AZ::NiceSettingsRegistrySimpleMock m_settings;
             SSystemGlobalEnvironment m_stubEnv;
             SSystemGlobalEnvironment m_stubEnv;
         };
         };
 
 
         AZStd::unique_ptr<DataMembers> m_data;
         AZStd::unique_ptr<DataMembers> m_data;
 
 
         SSystemGlobalEnvironment* m_priorEnv = nullptr;
         SSystemGlobalEnvironment* m_priorEnv = nullptr;
+        AZ::SettingsRegistryInterface* m_priorSettingsRegistry = nullptr;
     };
     };
 
 
     // allow punch through to PRIVATE functions so that they do not need to be made PUBLIC.
     // allow punch through to PRIVATE functions so that they do not need to be made PUBLIC.
@@ -130,7 +185,9 @@ namespace NRemoteCompiler
 
 
     TEST_F(RemoteCompilerTest, CShaderSrv_Constructor_WithNoGameName_Fails)
     TEST_F(RemoteCompilerTest, CShaderSrv_Constructor_WithNoGameName_Fails)
     {
     {
-        EXPECT_CALL(m_data->m_cvarMock, GetString());
+        using namespace ::testing;
+        AZ::SettingsRegistryInterface::FixedValueString regResult;
+        EXPECT_CALL(m_data->m_settings, Get(regResult, _));
 
 
         AZ_TEST_START_TRACE_SUPPRESSION;
         AZ_TEST_START_TRACE_SUPPRESSION;
         ShaderSrvUnitTestAccessor srv;
         ShaderSrvUnitTestAccessor srv;
@@ -140,8 +197,10 @@ namespace NRemoteCompiler
     TEST_F(RemoteCompilerTest, CShaderSrv_Constructor_WithValidGameName_Succeeds)
     TEST_F(RemoteCompilerTest, CShaderSrv_Constructor_WithValidGameName_Succeeds)
     {
     {
         // when we construct the server it calls get on the game name
         // when we construct the server it calls get on the game name
-        EXPECT_CALL(m_data->m_cvarMock, GetString())
-            .WillOnce(Return("StarterGame"));
+        using namespace ::testing;
+        AZ::SettingsRegistryInterface::FixedValueString projectName;
+        EXPECT_CALL(m_data->m_settings, Get(projectName, _))
+            .WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
 
 
         ShaderSrvUnitTestAccessor srv;
         ShaderSrvUnitTestAccessor srv;
     }
     }
@@ -149,11 +208,12 @@ namespace NRemoteCompiler
     TEST_F(RemoteCompilerTest, CShaderSrv_EncapsulateRequestInEngineConnectionProtocol_EmptyData_Fails)
     TEST_F(RemoteCompilerTest, CShaderSrv_EncapsulateRequestInEngineConnectionProtocol_EmptyData_Fails)
     {
     {
         // when we construct the server it calls get on the game name
         // when we construct the server it calls get on the game name
-        EXPECT_CALL(m_data->m_cvarMock, GetString())
-            .WillOnce(Return("StarterGame"));
+        using namespace ::testing;
+        AZ::SettingsRegistryInterface::FixedValueString projectName;
+        EXPECT_CALL(m_data->m_settings, Get(projectName, _))
+            .WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
 
 
         ShaderSrvUnitTestAccessor srv;
         ShaderSrvUnitTestAccessor srv;
-        
 
 
         std::vector<uint8> testVector;
         std::vector<uint8> testVector;
 
 
@@ -165,11 +225,12 @@ namespace NRemoteCompiler
     TEST_F(RemoteCompilerTest, CShaderSrv_EncapsulateRequestInEngineConnectionProtocol_ValidData_EmptyServerList_Fails)
     TEST_F(RemoteCompilerTest, CShaderSrv_EncapsulateRequestInEngineConnectionProtocol_ValidData_EmptyServerList_Fails)
     {
     {
         // when we construct the server it calls get on the game name
         // when we construct the server it calls get on the game name
-        EXPECT_CALL(m_data->m_cvarMock, GetString())
-            .WillOnce(Return("StarterGame"));
+        using namespace ::testing;
+        AZ::SettingsRegistryInterface::FixedValueString projectName;
+        EXPECT_CALL(m_data->m_settings, Get(projectName, _))
+            .WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
 
 
         ShaderSrvUnitTestAccessor srv;
         ShaderSrvUnitTestAccessor srv;
-        
 
 
         EXPECT_CALL(m_data->m_cvarMock, GetString())
         EXPECT_CALL(m_data->m_cvarMock, GetString())
             .WillRepeatedly(Return("")); // empty server list
             .WillRepeatedly(Return("")); // empty server list
@@ -186,11 +247,12 @@ namespace NRemoteCompiler
     TEST_F(RemoteCompilerTest, CShaderSrv_EncapsulateRequestInEngineConnectionProtocol_ValidInputs_Succeeds)
     TEST_F(RemoteCompilerTest, CShaderSrv_EncapsulateRequestInEngineConnectionProtocol_ValidInputs_Succeeds)
     {
     {
         // when we construct the server it calls get on the game name
         // when we construct the server it calls get on the game name
-        EXPECT_CALL(m_data->m_cvarMock, GetString())
-            .WillOnce(Return("StarterGame"));
+        using namespace ::testing;
+        AZ::SettingsRegistryInterface::FixedValueString projectName;
+        EXPECT_CALL(m_data->m_settings, Get(projectName, _))
+            .WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
 
 
         ShaderSrvUnitTestAccessor srv;
         ShaderSrvUnitTestAccessor srv;
-        
 
 
         // After this, it will repeatedly call get cvar to get the server address:
         // After this, it will repeatedly call get cvar to get the server address:
         const char* testList = "10.20.30.40";
         const char* testList = "10.20.30.40";
@@ -207,11 +269,12 @@ namespace NRemoteCompiler
     TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_EmptyData_Fails)
     TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_EmptyData_Fails)
     {
     {
         // when we construct the server it calls get on the game name
         // when we construct the server it calls get on the game name
-        EXPECT_CALL(m_data->m_cvarMock, GetString())
-            .WillOnce(Return("StarterGame"));
+        using namespace ::testing;
+        AZ::SettingsRegistryInterface::FixedValueString projectName;
+        EXPECT_CALL(m_data->m_settings, Get(projectName, _))
+            .WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
 
 
         ShaderSrvUnitTestAccessor srv;
         ShaderSrvUnitTestAccessor srv;
-        
 
 
         // After this, it will repeatedly call get cvar to get the server address:
         // After this, it will repeatedly call get cvar to get the server address:
         const char* testList = "10.20.30.40";
         const char* testList = "10.20.30.40";
@@ -221,7 +284,7 @@ namespace NRemoteCompiler
         std::vector<uint8> testVector;
         std::vector<uint8> testVector;
         std::string testString("empty");
         std::string testString("empty");
 
 
-        // test for empty data - recvfailed expected (error emitted)
+        // test for empty data - RecvFailed expected (error emitted)
         AZ_TEST_START_TRACE_SUPPRESSION;
         AZ_TEST_START_TRACE_SUPPRESSION;
         testString = "empty";
         testString = "empty";
         testVector.assign(testString.begin(), testString.end());
         testVector.assign(testString.begin(), testString.end());
@@ -232,11 +295,12 @@ namespace NRemoteCompiler
     TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_IncompleteData_Fails)
     TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_IncompleteData_Fails)
     {
     {
         // when we construct the server it calls get on the game name
         // when we construct the server it calls get on the game name
-        EXPECT_CALL(m_data->m_cvarMock, GetString())
-            .WillOnce(Return("StarterGame"));
+        using namespace ::testing;
+        AZ::SettingsRegistryInterface::FixedValueString projectName;
+        EXPECT_CALL(m_data->m_settings, Get(projectName, _))
+            .WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
 
 
         ShaderSrvUnitTestAccessor srv;
         ShaderSrvUnitTestAccessor srv;
-        
 
 
         // After this, it will repeatedly call get cvar to get the server address:
         // After this, it will repeatedly call get cvar to get the server address:
         const char* testList = "10.20.30.40";
         const char* testList = "10.20.30.40";
@@ -247,7 +311,7 @@ namespace NRemoteCompiler
         std::string testString("incomplete");
         std::string testString("incomplete");
         testVector.assign(testString.begin(), testString.end());
         testVector.assign(testString.begin(), testString.end());
 
 
-        // test for incomplete data - recvfailed expected
+        // test for incomplete data - RecvFailed expected
         AZ_TEST_START_TRACE_SUPPRESSION;
         AZ_TEST_START_TRACE_SUPPRESSION;
         EXPECT_EQ(srv.SendRequestViaEngineConnection(testVector), EServerError::ESRecvFailed);
         EXPECT_EQ(srv.SendRequestViaEngineConnection(testVector), EServerError::ESRecvFailed);
         AZ_TEST_STOP_TRACE_SUPPRESSION(1);
         AZ_TEST_STOP_TRACE_SUPPRESSION(1);
@@ -256,11 +320,12 @@ namespace NRemoteCompiler
     TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_CorruptData_Fails)
     TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_CorruptData_Fails)
     {
     {
         // when we construct the server it calls get on the game name
         // when we construct the server it calls get on the game name
-        EXPECT_CALL(m_data->m_cvarMock, GetString())
-            .WillOnce(Return("StarterGame"));
+        using namespace ::testing;
+        AZ::SettingsRegistryInterface::FixedValueString projectName;
+        EXPECT_CALL(m_data->m_settings, Get(projectName, _))
+            .WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
 
 
         ShaderSrvUnitTestAccessor srv;
         ShaderSrvUnitTestAccessor srv;
-        
 
 
         // After this, it will repeatedly call get cvar to get the server address:
         // After this, it will repeatedly call get cvar to get the server address:
         const char* testList = "10.20.30.40";
         const char* testList = "10.20.30.40";
@@ -271,7 +336,7 @@ namespace NRemoteCompiler
         std::string testString("corrupt");
         std::string testString("corrupt");
         testVector.assign(testString.begin(), testString.end());
         testVector.assign(testString.begin(), testString.end());
 
 
-        // test for incomplete data - recvfailed expected
+        // test for incomplete data - RecvFailed expected
         AZ_TEST_START_TRACE_SUPPRESSION;
         AZ_TEST_START_TRACE_SUPPRESSION;
         EXPECT_EQ(srv.SendRequestViaEngineConnection(testVector), EServerError::ESRecvFailed);
         EXPECT_EQ(srv.SendRequestViaEngineConnection(testVector), EServerError::ESRecvFailed);
         AZ_TEST_STOP_TRACE_SUPPRESSION(1);
         AZ_TEST_STOP_TRACE_SUPPRESSION(1);
@@ -280,11 +345,12 @@ namespace NRemoteCompiler
     TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_CompileError_Fails_ReturnsText)
     TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_CompileError_Fails_ReturnsText)
     {
     {
         // when we construct the server it calls get on the game name
         // when we construct the server it calls get on the game name
-        EXPECT_CALL(m_data->m_cvarMock, GetString())
-            .WillOnce(Return("StarterGame"));
+        using namespace ::testing;
+        AZ::SettingsRegistryInterface::FixedValueString projectName;
+        EXPECT_CALL(m_data->m_settings, Get(projectName, _))
+            .WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
 
 
         ShaderSrvUnitTestAccessor srv;
         ShaderSrvUnitTestAccessor srv;
-        
 
 
         // After this, it will repeatedly call get cvar to get the server address:
         // After this, it will repeatedly call get cvar to get the server address:
         const char* testList = "10.20.30.40";
         const char* testList = "10.20.30.40";
@@ -294,11 +360,11 @@ namespace NRemoteCompiler
         std::vector<uint8> testVector;
         std::vector<uint8> testVector;
         std::string testString("corrupt");
         std::string testString("corrupt");
         testVector.assign(testString.begin(), testString.end());
         testVector.assign(testString.begin(), testString.end());
-        // test for an actual compile error - decompressed compile erro rexpected to be attached.
+        // test for an actual compile error - decompressed compile error expected to be attached.
         testString = "compile_failure";
         testString = "compile_failure";
         testVector.assign(testString.begin(), testString.end());
         testVector.assign(testString.begin(), testString.end());
         EXPECT_EQ(srv.SendRequestViaEngineConnection(testVector), EServerError::ESCompileError);
         EXPECT_EQ(srv.SendRequestViaEngineConnection(testVector), EServerError::ESCompileError);
-        // validate hte compile erorr decompressed successfully
+        // validate the compile error decompressed successfully
         const char* expected_decode = "decompressed_plaintext";
         const char* expected_decode = "decompressed_plaintext";
         EXPECT_EQ(testVector.size(), strlen(expected_decode));
         EXPECT_EQ(testVector.size(), strlen(expected_decode));
         EXPECT_EQ(memcmp(testVector.data(), expected_decode, strlen(expected_decode)), 0);
         EXPECT_EQ(memcmp(testVector.data(), expected_decode, strlen(expected_decode)), 0);
@@ -307,11 +373,12 @@ namespace NRemoteCompiler
     TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_ValidInput_Succeeds_ReturnsText)
     TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_ValidInput_Succeeds_ReturnsText)
     {
     {
         // when we construct the server it calls get on the game name
         // when we construct the server it calls get on the game name
-        EXPECT_CALL(m_data->m_cvarMock, GetString())
-            .WillOnce(Return("StarterGame"));
+        using namespace ::testing;
+        AZ::SettingsRegistryInterface::FixedValueString projectName;
+        EXPECT_CALL(m_data->m_settings, Get(projectName, _))
+            .WillOnce(DoAll(testing::SetArgReferee<0>("StarterGame"), Return(true)));
 
 
         ShaderSrvUnitTestAccessor srv;
         ShaderSrvUnitTestAccessor srv;
-        
 
 
         // After this, it will repeatedly call get cvar to get the server address:
         // After this, it will repeatedly call get cvar to get the server address:
         const char* testList = "10.20.30.40";
         const char* testList = "10.20.30.40";

+ 4 - 3
Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp

@@ -375,7 +375,7 @@ void CShaderMan::mfInitShadersCacheMissLog()
     // create valid path
     // create valid path
     gEnv->pCryPak->MakeDir(g_szTestResults);
     gEnv->pCryPak->MakeDir(g_szTestResults);
 
 
-    m_ShaderCacheMissPath = string("@cache@\\Shaders\\ShaderCacheMisses.txt");  // do we want this here, or maybe in @log@ ?
+    m_ShaderCacheMissPath = string("@usercache@\\Shaders\\ShaderCacheMisses.txt");  // do we want this here, or maybe in @log@ ?
 
 
     // load data which is already stored
     // load data which is already stored
     AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
     AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
@@ -2175,9 +2175,10 @@ void CShaderMan::mfOptimiseShaders(const char* szFolder, bool bForce)
     for (i = 0; i < Names.size(); i++)
     for (i = 0; i < Names.size(); i++)
     {
     {
         const char* szName = Names[i].c_str();
         const char* szName = Names[i].c_str();
-        if (!strncmp(szName, "@cache@/", 7))
+        constexpr AZStd::string_view userCache = "@usercache@/";
+        if (szName == userCache)
         {
         {
-            szName += 7;
+            szName += userCache.size();
         }
         }
         pCache = CHWShader::mfInitCache(szName, NULL, false, 0, false);
         pCache = CHWShader::mfInitCache(szName, NULL, false, 0, false);
         if (!pCache || !pCache->m_pRes[CACHE_USER])
         if (!pCache || !pCache->m_pRes[CACHE_USER])

+ 1 - 1
Code/CryEngine/RenderDll/Common/Shaders/ShaderCore.cpp

@@ -1589,7 +1589,7 @@ void CShaderMan::mfInit (void)
 #else
 #else
         m_ShadersCache = CONCAT_PATHS(g_shaderCache, "D3D11");
         m_ShadersCache = CONCAT_PATHS(g_shaderCache, "D3D11");
 #endif
 #endif
-        m_szCachePath = "@cache@/";
+        m_szCachePath = "@usercache@/";
         
         
         if (CRenderer::CV_r_shadersImport == 3)
         if (CRenderer::CV_r_shadersImport == 3)
         {
         {

+ 1 - 1
Code/CryEngine/RenderDll/Common/Shaders/ShaderSerialize.cpp

@@ -162,7 +162,7 @@ bool CShaderSerialize::OpenSResource(const char* szName,  SSShaderRes* pSR, CSha
     stack_string szReadOnly = szName;
     stack_string szReadOnly = szName;
 
 
     // ShaderCacheGen behavior:
     // ShaderCacheGen behavior:
-    // CACHE_READONLY is not really used when exporting the .fxb, so we append the @cache@ alias to the relative shader path
+    // CACHE_READONLY is not really used when exporting the .fxb, so we append the @usercache@ alias to the relative shader path
     // here as well.  We cannot just leave this as the relative Shaders/Cache/Foo.fxb value because then it creates a new
     // here as well.  We cannot just leave this as the relative Shaders/Cache/Foo.fxb value because then it creates a new
     // file in the asset cache as @assets@/Shaders/Cache/Foo.fxb, which is illegal (since only AP has the authority to write here)
     // file in the asset cache as @assets@/Shaders/Cache/Foo.fxb, which is illegal (since only AP has the authority to write here)
     // Game runtime behavior:
     // Game runtime behavior:

+ 2 - 2
Code/CryEngine/RenderDll/XRenderD3D9/D3DHWShaderCompiling.cpp

@@ -3490,7 +3490,7 @@ void CHWShader_D3D::mfSaveCGFile(const char* scr, const char* path)
     }
     }
     else
     else
     {
     {
-        sprintf_s(name, "@cache@/shaders/fxerror/%s(GL%llx)/(LT%x)(RT%llx)/(MD%x)(MDV%x)(PSS%llx)(ST%llx).cg", GetName(), m_pCurInst->m_Ident.m_GLMask, m_pCurInst->m_Ident.m_LightMask, m_pCurInst->m_Ident.m_RTMask, m_pCurInst->m_Ident.m_MDMask, m_pCurInst->m_Ident.m_MDVMask, m_pCurInst->m_Ident.m_pipelineState.opaque, m_pCurInst->m_Ident.m_STMask);
+        sprintf_s(name, "@usercache@/shaders/fxerror/%s(GL%llx)/(LT%x)(RT%llx)/(MD%x)(MDV%x)(PSS%llx)(ST%llx).cg", GetName(), m_pCurInst->m_Ident.m_GLMask, m_pCurInst->m_Ident.m_LightMask, m_pCurInst->m_Ident.m_RTMask, m_pCurInst->m_Ident.m_MDMask, m_pCurInst->m_Ident.m_MDVMask, m_pCurInst->m_Ident.m_pipelineState.opaque, m_pCurInst->m_Ident.m_STMask);
     }
     }
 
 
     AZ::IO::HandleType fileHandle;
     AZ::IO::HandleType fileHandle;
@@ -4672,7 +4672,7 @@ bool CAsyncShaderTask::CompileAsyncShader(SShaderAsyncInfo* pAsync)
         CryFixedStringT<1024> hlslPath;
         CryFixedStringT<1024> hlslPath;
 
 
         // Create a directory for this shader type, strip the .fxcb extension from the folder name
         // Create a directory for this shader type, strip the .fxcb extension from the folder name
-        shaderSourceOutputFolder.Format("@cache@/%s",pAsync->m_pShader->m_pDevCache->m_Name.c_str());
+        shaderSourceOutputFolder.Format("@usercache@/%s",pAsync->m_pShader->m_pDevCache->m_Name.c_str());
         PathUtil::RemoveExtension(shaderSourceOutputFolder);
         PathUtil::RemoveExtension(shaderSourceOutputFolder);
         gEnv->pFileIO->CreatePath(shaderSourceOutputFolder);
         gEnv->pFileIO->CreatePath(shaderSourceOutputFolder);
 
 

+ 3 - 2
Code/CryEngine/RenderDll/XRenderD3D9/D3DSystem.cpp

@@ -70,6 +70,7 @@
 #endif
 #endif
 
 
 #include "../Common/RenderCapabilities.h"
 #include "../Common/RenderCapabilities.h"
+#include <AzCore/Utils/Utils.h>
 
 
 #ifdef WIN32
 #ifdef WIN32
 // Count monitors helper
 // Count monitors helper
@@ -1634,8 +1635,8 @@ WIN_HWND CD3D9Renderer::Init([[maybe_unused]] int x, [[maybe_unused]] int y, int
     iLog->Log ("Direct3D driver is creating...");
     iLog->Log ("Direct3D driver is creating...");
     iLog->Log ("Crytek Direct3D driver version %4.2f (%s <%s>)", VERSION_D3D, __DATE__, __TIME__);
     iLog->Log ("Crytek Direct3D driver version %4.2f (%s <%s>)", VERSION_D3D, __DATE__, __TIME__);
 
 
-    const char* sGameName = iConsole->GetCVar("sys_game_name")->GetString();
-    cry_strcpy(m_WinTitle, sGameName);
+    auto projectName = AZ::Utils::GetProjectName();
+    cry_strcpy(m_WinTitle, projectName.c_str());
 
 
     iLog->Log ("Creating window called '%s' (%dx%d)", m_WinTitle, width, height);
     iLog->Log ("Creating window called '%s' (%dx%d)", m_WinTitle, width, height);
 
 

+ 209 - 117
Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp

@@ -20,6 +20,8 @@
 #include <AzCore/Component/ComponentApplication.h>
 #include <AzCore/Component/ComponentApplication.h>
 #include <AzCore/Component/TickBus.h>
 #include <AzCore/Component/TickBus.h>
 
 
+#include <AzCore/Debug/LocalFileEventLogger.h>
+
 #include <AzCore/Memory/AllocationRecords.h>
 #include <AzCore/Memory/AllocationRecords.h>
 
 
 #include <AzCore/Memory/OverrunDetectionAllocator.h>
 #include <AzCore/Memory/OverrunDetectionAllocator.h>
@@ -99,6 +101,18 @@ namespace AZ
         return environment ? environment->Get() : nullptr;
         return environment ? environment->Get() : nullptr;
     }
     }
 
 
+    ComponentApplication::EventLoggerDeleter::EventLoggerDeleter() noexcept= default;
+    ComponentApplication::EventLoggerDeleter::EventLoggerDeleter(bool skipDelete) noexcept
+        : m_skipDelete{skipDelete}
+    {}
+    void ComponentApplication::EventLoggerDeleter::operator()(AZ::Debug::LocalFileEventLogger* ptr)
+    {
+        if (!m_skipDelete)
+        {
+            delete ptr;
+        }
+    }
+
     //=========================================================================
     //=========================================================================
     // ComponentApplication::Descriptor
     // ComponentApplication::Descriptor
     // [5/30/2012]
     // [5/30/2012]
@@ -159,6 +173,80 @@ namespace AZ
         return true;
         return true;
     };
     };
 
 
+    //! SettingsRegistry notifier handler which updates relevant registry settings based
+    //! on an update to '/Amazon/AzCore/Bootstrap/project_path' key.
+    struct UpdateProjectSettingsEventHandler
+    {
+        UpdateProjectSettingsEventHandler(AZ::SettingsRegistryInterface& registry)
+            : m_registry{ registry }
+        {
+        }
+
+        void operator()(AZStd::string_view path, AZ::SettingsRegistryInterface::Type)
+        {
+            UpdateProjectSpecializationInRegistry(path);
+        }
+
+        //! Add the project name as a specialization underneath the /Amazon/AzCore/Settings/Specializations path
+        //! and remove the current project name specialization if one exists.
+        void UpdateProjectSpecializationInRegistry(AZStd::string_view path)
+        {
+            auto projectPathKey =
+                AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)
+                + "/project_path";
+            if (path == projectPathKey)
+            {
+                AZ::SettingsRegistryInterface::FixedValueString newProjectPath;
+                if (m_registry.Get(newProjectPath, path) && !newProjectPath.empty())
+                {
+                    // Make the path absolute by appending to app root, in case project path is relative.
+                    // If the project path is already absolute it will remain the same.
+                    // If we turn it from a relative path to an absolute path, write-back the absolute path to the registry.
+                    AZ::IO::FixedMaxPath projectPath = AZ::SettingsRegistryMergeUtils::FindEngineRoot(m_registry) / newProjectPath;
+                    if (projectPath.Compare(newProjectPath.c_str()))
+                    {
+                        m_registry.Set(path, projectPath.Native());
+                    }
+
+                    // Merge the project.json file into settings registry under ProjectSettingsRootKey path.
+                    AZ::IO::FixedMaxPath projectMetadataFile{ projectPath };
+                    projectMetadataFile /= "project.json";
+                    m_registry.MergeSettingsFile(projectMetadataFile.Native(),
+                        AZ::SettingsRegistryInterface::Format::JsonMergePatch, AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey);
+
+                    // Get the 'project_name' value from what was in the 'project.json' file...
+                    auto projectNameKey =
+                        AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey)
+                        + "/project_name";
+
+                    AZ::SettingsRegistryInterface::FixedValueString projectSpecialization;
+                    if (m_registry.Get(projectSpecialization, projectNameKey))
+                    {
+                        auto specializationKey = AZ::SettingsRegistryInterface::FixedValueString::format(
+                            "%s/%s", AZ::SettingsRegistryMergeUtils::SpecializationsRootKey, projectSpecialization.c_str());
+                        if (m_currentSpecialization != specializationKey)
+                        {
+                            m_registry.Set(specializationKey, true);
+                            if (!m_currentSpecialization.empty())
+                            {
+                                // Remove the previous Project Name from the specialization path if it was set.
+                                m_registry.Remove(m_currentSpecialization);
+                            }
+                            m_currentSpecialization = specializationKey;
+
+                            // Update all the runtime file paths based on the new "project_path" value.
+                            AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry);
+                        }
+                    }
+                }
+            }
+        }
+
+    private:
+        AZ::SettingsRegistryInterface::FixedValueString m_currentSpecialization;
+        AZ::SettingsRegistryInterface& m_registry;
+    };
+
     void ComponentApplication::Descriptor::AllocatorRemapping::Reflect(ReflectContext* context, ComponentApplication* app)
     void ComponentApplication::Descriptor::AllocatorRemapping::Reflect(ReflectContext* context, ComponentApplication* app)
     {
     {
         (void)app;
         (void)app;
@@ -276,6 +364,7 @@ namespace AZ
     }
     }
 
 
     ComponentApplication::ComponentApplication(int argC, char** argV)
     ComponentApplication::ComponentApplication(int argC, char** argV)
+        : m_eventLogger{}
     {
     {
         if (argV)
         if (argV)
         {
         {
@@ -284,11 +373,23 @@ namespace AZ
         }
         }
         else
         else
         {
         {
-            azstrcpy(m_commandLineBuffer, AZ_ARRAY_SIZE(m_commandLineBuffer), "no_argv_supplied");
+             azstrcpy(m_commandLineBuffer, AZ_ARRAY_SIZE(m_commandLineBuffer), "no_argv_supplied");
             // use a "valid" value here.  This is because Qt and potentially other third party libraries require
             // use a "valid" value here.  This is because Qt and potentially other third party libraries require
             // that ArgC be 'at least 1' and that (*argV)[0] be a valid pointer to a real null terminated string.
             // that ArgC be 'at least 1' and that (*argV)[0] be a valid pointer to a real null terminated string.
-            m_argC = 1;
-            m_argV = &m_commandLineBufferAddress;
+             m_argC = 1;
+             m_argV = &m_commandLineBufferAddress;
+        }
+
+        // Create the Event logger if it doesn't exist, otherwise reuse the one registered
+        // with the AZ::Interface
+        if (AZ::Interface<AZ::Debug::IEventLogger>::Get() == nullptr)
+        {
+            m_eventLogger.reset(new AZ::Debug::LocalFileEventLogger);
+        }
+        else
+        {
+            m_eventLogger = EventLoggerPtr(static_cast<AZ::Debug::LocalFileEventLogger*>(AZ::Interface<AZ::Debug::IEventLogger>::Get()),
+                EventLoggerDeleter{ true });
         }
         }
 
 
         // Initializes the OSAllocator and SystemAllocator as soon as possible
         // Initializes the OSAllocator and SystemAllocator as soon as possible
@@ -297,6 +398,7 @@ namespace AZ
 
 
         // Now that the Allocators are initialized, the Command Line parameters can be parsed
         // Now that the Allocators are initialized, the Command Line parameters can be parsed
         m_commandLine.Parse(m_argC, m_argV);
         m_commandLine.Parse(m_argC, m_argV);
+        ParseCommandLine(m_commandLine);
 
 
         // Create the settings registry and register it with the AZ interface system
         // Create the settings registry and register it with the AZ interface system
         // This is done after the AppRoot has been calculated so that the Bootstrap.cfg
         // This is done after the AppRoot has been calculated so that the Bootstrap.cfg
@@ -304,62 +406,34 @@ namespace AZ
         m_settingsRegistry = AZStd::make_unique<SettingsRegistryImpl>();
         m_settingsRegistry = AZStd::make_unique<SettingsRegistryImpl>();
 
 
         // Register the Settings Registry with the AZ Interface if there isn't one registered already
         // Register the Settings Registry with the AZ Interface if there isn't one registered already
-        if (AZ::SettingsRegistry::Get() == nullptr)
+        if (SettingsRegistry::Get() == nullptr)
         {
         {
             SettingsRegistry::Register(m_settingsRegistry.get());
             SettingsRegistry::Register(m_settingsRegistry.get());
         }
         }
 
 
         // Add the Command Line arguments into the SettingsRegistry
         // Add the Command Line arguments into the SettingsRegistry
-        AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_StoreCommandLine(*m_settingsRegistry, m_commandLine);
+        SettingsRegistryMergeUtils::StoreCommandLineToRegistry(*m_settingsRegistry, m_commandLine);
+
+        // Merge Command Line arguments 
+        constexpr bool executeRegDumpCommands = false;
+        SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
 
 
         // Query for the Executable Path using OS specific functions
         // Query for the Executable Path using OS specific functions
         CalculateExecutablePath();
         CalculateExecutablePath();
-        // If the current platform returns an engaged optional from Utils::GetDefaultAppRootPath(), that is used
-        // for the application root other the application root is found by scanning upwards from the Executable Directory
-        // for a bootstrap.cfg file
-        CalculateAppRoot(nullptr);
-
-        // Add a notifier to update the /Amazon/AzCore/Settings/Specializations
-        // when the sys_game_folder property changes within the SettingsRegistry
 
 
-        // currentGameName is bound by value in order to allow the lambda to have a member variable that
-        // can track the current game specialization before it changes
-        AZ::SettingsRegistryInterface::FixedValueString currentGameSpecialization;
-        auto GameProjectChanged = [currentGameSpecialization](AZStd::string_view path, AZ::SettingsRegistryInterface::Type type) mutable
-        {
-            constexpr auto projectKey = AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)
-                + "/sys_game_folder";
-            if (projectKey == path && type == AZ::SettingsRegistryInterface::Type::String)
-            {
-                auto registry = AZ::SettingsRegistry::Get();
-                AZ::SettingsRegistryInterface::FixedValueString newGameName;
-                if (registry && registry->Get(newGameName, path) && !newGameName.empty())
-                {
-                    auto specializationKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/%s",
-                        AZ::SettingsRegistryMergeUtils::SpecializationsRootKey, newGameName.c_str());
+        // Determine the path to the engine
+        CalculateEngineRoot();
 
 
-                    if (currentGameSpecialization != specializationKey)
-                    {
-                        registry->Set(specializationKey, true);
-                        if (!currentGameSpecialization.empty())
-                        {
-                            // Remove the previous Game Name from the specialization path if it was set
-                            registry->Remove(currentGameSpecialization);
-                        }
-                        // Update the currentGameSpecialization
-                        currentGameSpecialization = specializationKey;
+        // If the current platform returns an engaged optional from Utils::GetDefaultAppRootPath(), that is used
+        // for the application root.
+        CalculateAppRoot();
 
 
-                        // Update all the runtime filepaths based on the new "sys_game_folder" value
-                        SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry);
-                    }
-                }
-            }
-        };
-        m_gameProjectChangedHandler = m_settingsRegistry->RegisterNotifier(AZStd::move(GameProjectChanged));
+        // Add a notifier to update the /Amazon/AzCore/Settings/Specializations
+        // when the 'project_path' property changes within the SettingsRegistry
+        m_projectChangedHandler = m_settingsRegistry->RegisterNotifier(UpdateProjectSettingsEventHandler{ *m_settingsRegistry });
 
 
         // Merge the bootstrap.cfg file into the Settings Registry as soon as the OSAllocator has been created.
         // Merge the bootstrap.cfg file into the Settings Registry as soon as the OSAllocator has been created.
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(*m_settingsRegistry);
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(*m_settingsRegistry);
-        constexpr bool executeRegDumpCommands = false;
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*m_settingsRegistry);
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*m_settingsRegistry);
 
 
@@ -391,11 +465,11 @@ namespace AZ
             Destroy();
             Destroy();
         }
         }
 
 
-        // The m_gameProjectChangedHandler stores an AZStd::function internally
+        // The m_projectChangedHandler stores an AZStd::function internally
         // which allocates using the AZ SystemAllocator
         // which allocates using the AZ SystemAllocator
-        // m_gameProjectChangedHandler is being default value initialized
+        // m_projectChangedHandler is being default value initialized
         // to clear out the AZStd::function
         // to clear out the AZStd::function
-        m_gameProjectChangedHandler = {};
+        m_projectChangedHandler = {};
 
 
         // Delete the AZ::IConsole if it was created by this application instance
         // Delete the AZ::IConsole if it was created by this application instance
         if (m_ownsConsole)
         if (m_ownsConsole)
@@ -412,6 +486,10 @@ namespace AZ
         }
         }
         m_settingsRegistry.reset();
         m_settingsRegistry.reset();
 
 
+        // Set AZ::CommandLine to an empty object to clear out allocated memory before the allocators
+        // are destroyed
+        m_commandLine = {};
+
         DestroyAllocator();
         DestroyAllocator();
     }
     }
 
 
@@ -421,17 +499,6 @@ namespace AZ
         AZ_Assert(!m_isStarted, "Component application already started!");
         AZ_Assert(!m_isStarted, "Component application already started!");
 
 
         m_startupParameters = startupParameters;
         m_startupParameters = startupParameters;
-        // Invokes CalculateAppRoot() again this time with the appRootOverride startup parameter
-        // supplied in order to allow overriding the AppRoot calculated in the constructor
-        if (m_startupParameters.m_appRootOverride)
-        {
-            CalculateAppRoot(m_startupParameters.m_appRootOverride);
-            // Re-check for the bootstrap.cfg file again using the appRoot override and update the file paths
-            SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(*m_settingsRegistry);
-            constexpr bool executeRegDumpCommands = false;
-            SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
-            SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*m_settingsRegistry);
-        }
 
 
         m_descriptor = descriptor;
         m_descriptor = descriptor;
 
 
@@ -461,20 +528,14 @@ namespace AZ
     void ComponentApplication::CreateCommon()
     void ComponentApplication::CreateCommon()
     {
     {
         {
         {
-            AZ::SettingsRegistryInterface::FixedValueString registryValue;
-            m_settingsRegistry->Get(registryValue, AZ::SettingsRegistryMergeUtils::FilePathKey_DevWriteStorage);
-            AZ::IO::FixedMaxPath outputPath{ registryValue };
+            AZ::IO::FixedMaxPath outputPath;
+            m_settingsRegistry->Get(outputPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_DevWriteStorage);
             outputPath /= "eventlogger";
             outputPath /= "eventlogger";
 
 
-            registryValue.clear();
-
             AZ::IO::FixedMaxPathString baseFileName{ "EventLog" }; // default name
             AZ::IO::FixedMaxPathString baseFileName{ "EventLog" }; // default name
-            if (m_settingsRegistry->Get(registryValue, AZ::SettingsRegistryMergeUtils::BuildTargetNameKey))
-            {
-                baseFileName = registryValue;
-            }
+            m_settingsRegistry->Get(baseFileName, AZ::SettingsRegistryMergeUtils::BuildTargetNameKey);
 
 
-            m_eventLogger.Start(outputPath.c_str(), baseFileName.c_str());
+            m_eventLogger->Start(outputPath.Native(), baseFileName);
         }
         }
 
 
         CreateDrillers();
         CreateDrillers();
@@ -515,7 +576,9 @@ namespace AZ
         LoadModules();
         LoadModules();
 
 
         // Execute user.cfg after modules have been loaded but before processing any command-line overrides
         // Execute user.cfg after modules have been loaded but before processing any command-line overrides
-        m_console->ExecuteConfigFile("@root@/user.cfg");
+        AZ::IO::FixedMaxPath platformCachePath;
+        m_settingsRegistry->Get(platformCachePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder);
+        m_console->ExecuteConfigFile((platformCachePath / "user.cfg").Native());
 
 
         // Parse the command line parameters for console commands after modules have loaded
         // Parse the command line parameters for console commands after modules have loaded
         m_console->ExecuteCommandLine(m_commandLine);
         m_console->ExecuteCommandLine(m_commandLine);
@@ -601,7 +664,7 @@ namespace AZ
             m_drillerManager = nullptr;
             m_drillerManager = nullptr;
         }
         }
 
 
-        m_eventLogger.Stop();
+        m_eventLogger->Stop();
 
 
         // Clear the descriptor to deallocate all strings (owned by ModuleDescriptor)
         // Clear the descriptor to deallocate all strings (owned by ModuleDescriptor)
         m_descriptor = Descriptor();
         m_descriptor = Descriptor();
@@ -775,6 +838,46 @@ namespace AZ
         }
         }
     }
     }
 
 
+    void ComponentApplication::ParseCommandLine(const AZ::CommandLine& commandLine)
+    {
+        struct OptionKeyToRegsetKey
+        {
+            AZStd::string_view m_optionKey;
+            AZStd::string m_regsetKey;
+        };
+
+        // Provide overrides for the engine root, the project root and the project cache root
+        AZStd::array commandOptions = {
+            OptionKeyToRegsetKey{ "engine-path", AZStd::string::format("%s/engine_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) },
+            OptionKeyToRegsetKey{ "project-path", AZStd::string::format("%s/project_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) },
+            OptionKeyToRegsetKey{ "project-cache-path", AZStd::string::format("%s/project_cache_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) }
+        };
+
+        AZStd::fixed_vector<AZStd::string, commandOptions.size()> overrideArgs;
+
+        for (auto&& [optionKey, regsetKey] : commandOptions)
+        {
+            if (size_t optionCount = commandLine.GetNumSwitchValues(optionKey); optionCount > 0)
+            {
+                // Use the last supplied command option value to override previous values
+                auto overrideArg = AZStd::string::format(R"(--regset="%s=%s")", regsetKey.c_str(),
+                    commandLine.GetSwitchValue(optionKey, optionCount - 1).c_str());
+                overrideArgs.emplace_back(AZStd::move(overrideArg));
+            }
+        }
+
+        if (!overrideArgs.empty())
+        {
+            // Dump the input command line, add the additional option overrides
+            // and Parse the new command line into the Component Application command line
+            AZ::CommandLine::ParamContainer commandLineArgs;
+            commandLine.Dump(commandLineArgs);
+            commandLineArgs.insert(commandLineArgs.end(), AZStd::make_move_iterator(overrideArgs.begin()),
+                AZStd::make_move_iterator(overrideArgs.end()));
+            m_commandLine.Parse(commandLineArgs);
+        }
+    }
+
     void ComponentApplication::MergeSettingsToRegistry(SettingsRegistryInterface& registry)
     void ComponentApplication::MergeSettingsToRegistry(SettingsRegistryInterface& registry)
     {
     {
         SettingsRegistryInterface::Specializations specializations;
         SettingsRegistryInterface::Specializations specializations;
@@ -788,14 +891,14 @@ namespace AZ
         // In development builds apply the developer registry and the command line to allow early overrides. This will
         // In development builds apply the developer registry and the command line to allow early overrides. This will
         // allow developers to override things like default paths or Asset Processor connection settings. Any additional
         // allow developers to override things like default paths or Asset Processor connection settings. Any additional
         // values will be replaced by later loads, so this step will happen again at the end of loading.
         // values will be replaced by later loads, so this step will happen again at the end of loading.
-        SettingsRegistryMergeUtils::MergeSettingsToRegistry_DevRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
+        SettingsRegistryMergeUtils::MergeSettingsToRegistry_UserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false);
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false);
 #endif
 #endif
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_EngineRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_EngineRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_GemRegistries(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_GemRegistries(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
 #if defined(AZ_DEBUG_BUILD) || defined(AZ_PROFILE_BUILD)
 #if defined(AZ_DEBUG_BUILD) || defined(AZ_PROFILE_BUILD)
-        SettingsRegistryMergeUtils::MergeSettingsToRegistry_DevRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
+        SettingsRegistryMergeUtils::MergeSettingsToRegistry_UserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true);
         SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true);
 #endif
 #endif
     }
     }
@@ -1013,7 +1116,7 @@ namespace AZ
         struct GemModuleLoadData
         struct GemModuleLoadData
         {
         {
             AZ::OSString m_gemName;
             AZ::OSString m_gemName;
-            AZ::OSString m_dynamicLibraryPath;
+            AZStd::vector<AZ::OSString> m_dynamicLibraryPaths;
             bool m_autoLoad{ true };
             bool m_autoLoad{ true };
         };
         };
 
 
@@ -1069,19 +1172,18 @@ namespace AZ
                 }
                 }
             }
             }
 
 
-            void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override
+            void Visit(AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override
             {
             {
-                if (valueName == "Module" && !value.empty())
+                // Remove last path segment and check if the key corresponds to the Modules array
+                AZStd::optional<AZStd::string_view> moduleIndex = AZ::StringFunc::TokenizeLast(path, "/");
+                if (path.ends_with("/Modules"))
                 {
                 {
-                    // Strip off the Module entry from the path
-                    auto moduleKey = AZ::StringFunc::TokenizeLast(path, "/");
-                    if (!moduleKey)
-                    {
-                        return;
-                    }
+                    // Remove the "Modules" path segment to be at the GemName key
+                    AZ::StringFunc::TokenizeLast(path, "/");
                     if (auto moduleLoadData = FindGemModuleEntry(path); moduleLoadData != nullptr)
                     if (auto moduleLoadData = FindGemModuleEntry(path); moduleLoadData != nullptr)
                     {
                     {
-                        moduleLoadData->m_dynamicLibraryPath = value;
+                        // Just use Json Serialization to load all the array elements
+                        moduleLoadData->m_dynamicLibraryPaths.emplace_back(value);
                     }
                     }
                 }
                 }
             }
             }
@@ -1111,30 +1213,41 @@ namespace AZ
             }
             }
         };
         };
 
 
-        constexpr size_t RegistryKeySize = 64;
-        auto gemModuleKey = AZStd::fixed_string<RegistryKeySize>::format("%s/Gems", AZ::SettingsRegistryMergeUtils::OrganizationRootKey);
+        auto gemModuleKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/Gems", AZ::SettingsRegistryMergeUtils::OrganizationRootKey);
         ModuleDescriptorList gemModules;
         ModuleDescriptorList gemModules;
         {
         {
             GemModuleVisitor moduleVisitor;
             GemModuleVisitor moduleVisitor;
-                m_settingsRegistry->Visit(moduleVisitor, gemModuleKey);
+            m_settingsRegistry->Visit(moduleVisitor, gemModuleKey);
             for (GemModuleLoadData& moduleLoadData : moduleVisitor.m_modulesLoadData)
             for (GemModuleLoadData& moduleLoadData : moduleVisitor.m_modulesLoadData)
             {
             {
                 // Add all auto loadable non-asset gems to the list of gem modules to load
                 // Add all auto loadable non-asset gems to the list of gem modules to load
-                if (moduleLoadData.m_autoLoad && !moduleLoadData.m_dynamicLibraryPath.empty())
+                if (!moduleLoadData.m_autoLoad)
                 {
                 {
-                    gemModules.emplace_back(DynamicModuleDescriptor{ AZStd::move(moduleLoadData.m_dynamicLibraryPath) });
+                    break;
+                }
+                for (AZ::OSString& dynamicLibraryPath : moduleLoadData.m_dynamicLibraryPaths)
+                {
+                    auto CompareDynamicModuleDescriptor = [&dynamicLibraryPath](const DynamicModuleDescriptor& entry)
+                    {
+                        return entry.m_dynamicLibraryPath.contains(dynamicLibraryPath);
+                    };
+                    if (auto moduleIter = AZStd::find_if(gemModules.begin(), gemModules.end(), CompareDynamicModuleDescriptor);
+                        moduleIter == gemModules.end())
+                    {
+                        gemModules.emplace_back(DynamicModuleDescriptor{ AZStd::move(dynamicLibraryPath) });
+                    }
                 }
                 }
             }
             }
         }
         }
 
 
-        // The settings registry in the settings registry are prioritized to load before the modules in the ComponetnApplication descriptor
+        // The modules in the settings registry are prioritized to load before the modules in the ComponentApplication descriptor
         // in the order in which they were found
         // in the order in which they were found
         for (auto&& moduleDescriptor : m_descriptor.m_modules)
         for (auto&& moduleDescriptor : m_descriptor.m_modules)
         {
         {
             // Append new dynamic library modules to the descriptor array
             // Append new dynamic library modules to the descriptor array
             auto CompareDynamicModuleDescriptor = [&moduleDescriptor](const DynamicModuleDescriptor& entry)
             auto CompareDynamicModuleDescriptor = [&moduleDescriptor](const DynamicModuleDescriptor& entry)
             {
             {
-                return entry.m_dynamicLibraryPath.find(moduleDescriptor.m_dynamicLibraryPath) != AZStd::string_view::npos;
+                return entry.m_dynamicLibraryPath.contains(moduleDescriptor.m_dynamicLibraryPath);
             };
             };
             if (auto foundModuleIter = AZStd::find_if(gemModules.begin(), gemModules.end(), CompareDynamicModuleDescriptor);
             if (auto foundModuleIter = AZStd::find_if(gemModules.begin(), gemModules.end(), CompareDynamicModuleDescriptor);
                 foundModuleIter == gemModules.end())
                 foundModuleIter == gemModules.end())
@@ -1260,17 +1373,8 @@ namespace AZ
         m_exeDirectory.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
         m_exeDirectory.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
     }
     }
 
 
-    void ComponentApplication::CalculateAppRoot(const char* appRootOverride)
+    void ComponentApplication::CalculateAppRoot()
     {
     {
-        if (appRootOverride)
-        {
-            m_appRoot = appRootOverride;
-            if (!m_appRoot.empty() && !m_appRoot.ends_with(AZ_CORRECT_FILESYSTEM_SEPARATOR))
-            {
-                m_appRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
-            }
-            return;
-        }
         if (AZStd::optional<AZ::StringFunc::Path::FixedString> appRootPath = Utils::GetDefaultAppRootPath(); appRootPath)
         if (AZStd::optional<AZ::StringFunc::Path::FixedString> appRootPath = Utils::GetDefaultAppRootPath(); appRootPath)
         {
         {
             m_appRoot = AZStd::move(*appRootPath);
             m_appRoot = AZStd::move(*appRootPath);
@@ -1279,26 +1383,14 @@ namespace AZ
                 m_appRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
                 m_appRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
             }
             }
         }
         }
-        else
-        {
-            m_appRoot = AZ::SettingsRegistryMergeUtils::GetAppRoot(m_settingsRegistry.get()).Native();
-            m_appRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
-        }
     }
     }
 
 
-    //=========================================================================
-    // CheckEngineMarkerFile
-    //=========================================================================
-    bool ComponentApplication::CheckPathForEngineMarker(const char* fullPath) const
+    void ComponentApplication::CalculateEngineRoot()
     {
     {
-        static const char* engineMarkerFileName = "engine.json";
-        char engineMarkerFullPathToCheck[AZ_MAX_PATH_LEN] = "";
-
-        azstrcpy(engineMarkerFullPathToCheck, AZ_ARRAY_SIZE(engineMarkerFullPathToCheck), fullPath);
-        azstrcat(engineMarkerFullPathToCheck, AZ_ARRAY_SIZE(engineMarkerFullPathToCheck), "/");
-        azstrcat(engineMarkerFullPathToCheck, AZ_ARRAY_SIZE(engineMarkerFullPathToCheck), engineMarkerFileName);
-
-        return AZ::IO::SystemFile::Exists(engineMarkerFullPathToCheck);
+        if (m_engineRoot = AZ::SettingsRegistryMergeUtils::FindEngineRoot(*m_settingsRegistry).Native(); !m_engineRoot.empty())
+        {
+            m_engineRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
+        }
     }
     }
 
 
     void ComponentApplication::ResolveModulePath([[maybe_unused]] AZ::OSString& modulePath)
     void ComponentApplication::ResolveModulePath([[maybe_unused]] AZ::OSString& modulePath)

+ 32 - 34
Code/Framework/AzCore/AzCore/Component/ComponentApplication.h

@@ -9,15 +9,13 @@
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 *
 */
 */
-#ifndef AZCORE_COMPONENT_APPLICATION_H
-#define AZCORE_COMPONENT_APPLICATION_H
+#pragma once
 
 
 #include <AzCore/Component/ComponentApplicationBus.h>
 #include <AzCore/Component/ComponentApplicationBus.h>
 #include <AzCore/Component/Component.h>
 #include <AzCore/Component/Component.h>
 #include <AzCore/Component/Entity.h>
 #include <AzCore/Component/Entity.h>
 #include <AzCore/Component/TickBus.h>
 #include <AzCore/Component/TickBus.h>
 #include <AzCore/Debug/ProfileModuleInit.h>
 #include <AzCore/Debug/ProfileModuleInit.h>
-#include <AzCore/Debug/LocalFileEventLogger.h>
 #include <AzCore/Memory/AllocationRecords.h>
 #include <AzCore/Memory/AllocationRecords.h>
 #include <AzCore/Memory/OSAllocator.h>
 #include <AzCore/Memory/OSAllocator.h>
 #include <AzCore/Module/DynamicModuleHandle.h>
 #include <AzCore/Module/DynamicModuleHandle.h>
@@ -40,12 +38,15 @@ namespace AZ
     class IConsole;
     class IConsole;
     class Module;
     class Module;
     class ModuleManager;
     class ModuleManager;
+}
+namespace AZ::Debug
+{
+    class DrillerManager;
+    class LocalFileEventLogger;
+}
 
 
-    namespace Debug
-    {
-        class DrillerManager;
-    }
-
+namespace AZ
+{
     class ReflectionEnvironment
     class ReflectionEnvironment
     {
     {
     public:
     public:
@@ -167,15 +168,6 @@ namespace AZ
             //! \note Dynamic AZ::Modules are specified in the ComponentApplication::Descriptor.
             //! \note Dynamic AZ::Modules are specified in the ComponentApplication::Descriptor.
             CreateStaticModulesCallback m_createStaticModulesCallback = nullptr;
             CreateStaticModulesCallback m_createStaticModulesCallback = nullptr;
 
 
-            //! If set, this is used as the app root folder instead of it being calculated.
-            const char* m_appRootOverride = nullptr;
-
-            //! The path to root of the asset cache folder. For instance: ./cache/<project>/pc
-            const char* m_cacheRootPath = nullptr;
-
-            //! The path to the project in the asset cache folder.  For instance: ./cache/<project>/pc/<project>
-            const char* m_cacheProjectPath = nullptr;
-
             //! Specifies which system components to create & activate. If no tags specified, all system components are used. Specify as comma separated list.
             //! Specifies which system components to create & activate. If no tags specified, all system components are used. Specify as comma separated list.
             const char* m_systemComponentTags = nullptr;
             const char* m_systemComponentTags = nullptr;
 
 
@@ -226,6 +218,8 @@ namespace AZ
         /// Returns the working root folder that has been registered with the app, if there is one.
         /// Returns the working root folder that has been registered with the app, if there is one.
         /// It's expected that derived applications will implement an application root.
         /// It's expected that derived applications will implement an application root.
         const char* GetAppRoot() const override { return m_appRoot.c_str(); }
         const char* GetAppRoot() const override { return m_appRoot.c_str(); }
+        /// Returns the path to the engine.
+        const char* GetEngineRoot() const override { return m_engineRoot.c_str(); }
         /// Returns the path to the folder the executable is in.
         /// Returns the path to the folder the executable is in.
         const char* GetExecutableFolder() const override { return m_exeDirectory.c_str(); }
         const char* GetExecutableFolder() const override { return m_exeDirectory.c_str(); }
 
 
@@ -331,6 +325,9 @@ namespace AZ
         /// Create the drillers
         /// Create the drillers
         void        CreateDrillers();
         void        CreateDrillers();
 
 
+        /// Parse ComponentApplication specific command line arguments
+        void ParseCommandLine(const AZ::CommandLine& commandLine);
+
         virtual void MergeSettingsToRegistry(SettingsRegistryInterface& registry);
         virtual void MergeSettingsToRegistry(SettingsRegistryInterface& registry);
 
 
         //! Sets the specializations that will be used when loading the Settings Registry. Extend this in derived
         //! Sets the specializations that will be used when loading the Settings Registry. Extend this in derived
@@ -363,17 +360,11 @@ namespace AZ
         /// Calculates the directory the application executable comes from.
         /// Calculates the directory the application executable comes from.
         void CalculateExecutablePath();
         void CalculateExecutablePath();
 
 
-        /// Calculates the directory where the bootstrap.cfg file resides.
-        void CalculateAppRoot(const char* appRootOverride = {});
+        /// Calculates the root directory of the engine.
+        void CalculateEngineRoot();
 
 
-        /**
-         * Check/verify a given path for the engine marker (file) so that we can identify that
-         * a given path is the engine root. This is only valid for target platforms that are built
-         * for the host platform and not deployable (ie windows, mac).
-         * @param fullPath The full path to look for the engine marker
-         * @return true if the input path contains the engine marker file, false if not
-         */
-        virtual bool CheckPathForEngineMarker(const char* fullPath) const;
+        /// Calculates the directory where the bootstrap.cfg file resides.
+        void CalculateAppRoot();
 
 
         template<typename Iterator>
         template<typename Iterator>
         static void NormalizePath(Iterator begin, Iterator end, bool doLowercase = true)
         static void NormalizePath(Iterator begin, Iterator end, bool doLowercase = true)
@@ -398,10 +389,11 @@ namespace AZ
         void*                                       m_fixedMemoryBlock{ nullptr }; //!< Pointer to the memory block allocator, so we can free it OnDestroy.
         void*                                       m_fixedMemoryBlock{ nullptr }; //!< Pointer to the memory block allocator, so we can free it OnDestroy.
         IAllocatorAllocate*                         m_osAllocator{ nullptr };
         IAllocatorAllocate*                         m_osAllocator{ nullptr };
         EntitySetType                               m_entities;
         EntitySetType                               m_entities;
-        AZ::StringFunc::Path::FixedString           m_exeDirectory;
-        AZ::StringFunc::Path::FixedString           m_appRoot;
+        AZ::IO::FixedMaxPathString                  m_exeDirectory;
+        AZ::IO::FixedMaxPathString                  m_engineRoot;
+        AZ::IO::FixedMaxPathString                  m_appRoot;
 
 
-        AZ::SettingsRegistryInterface::NotifyEventHandler m_gameProjectChangedHandler;
+        AZ::SettingsRegistryInterface::NotifyEventHandler m_projectChangedHandler;
 
 
         // ConsoleFunctorHandle is responsible for unregistering the Settings Registry Console
         // ConsoleFunctorHandle is responsible for unregistering the Settings Registry Console
         // from the m_console member when it goes out of scope
         // from the m_console member when it goes out of scope
@@ -427,9 +419,15 @@ namespace AZ
         // Created early to allow events to be logged before anything else. These will be kept in memory until
         // Created early to allow events to be logged before anything else. These will be kept in memory until
         // a file is associated with the logger. The internal buffer is limited to 64kb and once full unexpected
         // a file is associated with the logger. The internal buffer is limited to 64kb and once full unexpected
         // behavior may happen. The LocalFileEventLogger will register itself automatically with AZ::Interface<IEventLogger>.
         // behavior may happen. The LocalFileEventLogger will register itself automatically with AZ::Interface<IEventLogger>.
-        AZ::Debug::LocalFileEventLogger             m_eventLogger;
+
+        struct EventLoggerDeleter
+        {
+            EventLoggerDeleter() noexcept;
+            EventLoggerDeleter(bool skipDelete) noexcept;
+            void operator()(AZ::Debug::LocalFileEventLogger* ptr);
+            bool m_skipDelete{};
+        };
+        using EventLoggerPtr = AZStd::unique_ptr<AZ::Debug::LocalFileEventLogger, EventLoggerDeleter>;
+        EventLoggerPtr m_eventLogger;
     };
     };
 }
 }
-
-#endif // AZCORE_COMPONENT_APPLICATION_H
-#pragma once

+ 5 - 0
Code/Framework/AzCore/AzCore/Component/ComponentApplicationBus.h

@@ -183,6 +183,11 @@ namespace AZ
          * @return A pointer to the name of the app's root folder, if a root folder was registered.
          * @return A pointer to the name of the app's root folder, if a root folder was registered.
          */
          */
         virtual const char*             GetAppRoot() const = 0;
         virtual const char*             GetAppRoot() const = 0;
+        /**
+         * Gets the path of the working engine folder that the app is a part of.
+         * @return A pointer to the engine path.
+         */
+        virtual const char*             GetEngineRoot() const = 0;
         /**
         /**
          * Gets the path to the directory that contains the application's executable.
          * Gets the path to the directory that contains the application's executable.
          * @return A pointer to the name of the path that contains the application's executable.
          * @return A pointer to the name of the path that contains the application's executable.

+ 4 - 2
Code/Framework/AzCore/AzCore/Console/Console.cpp

@@ -161,9 +161,11 @@ namespace AZ
 
 
     void Console::ExecuteCommandLine(const AZ::CommandLine& commandLine)
     void Console::ExecuteCommandLine(const AZ::CommandLine& commandLine)
     {
     {
-        for (const auto& [switchKey, switchValues] : commandLine.GetSwitchList())
+        for (auto&& commandArgument : commandLine)
         {
         {
-            ConsoleCommandContainer commandArgs(switchValues.begin(), switchValues.end());
+            const auto& switchKey = commandArgument.m_option;
+            const auto& switchValue = commandArgument.m_value;
+            ConsoleCommandContainer commandArgs{ switchValue };
             PerformCommand(switchKey, commandArgs, ConsoleSilentMode::NotSilent, ConsoleInvokedFrom::AzConsole, ConsoleFunctorFlags::Null, ConsoleFunctorFlags::Null);
             PerformCommand(switchKey, commandArgs, ConsoleSilentMode::NotSilent, ConsoleInvokedFrom::AzConsole, ConsoleFunctorFlags::Null, ConsoleFunctorFlags::Null);
         }
         }
     }
     }

+ 14 - 25
Code/Framework/AzCore/AzCore/IO/FileIO.h

@@ -67,25 +67,7 @@ namespace AZ
             return a != OpenMode::Invalid;
             return a != OpenMode::Invalid;
         }
         }
 
 
-        inline OpenMode operator | (OpenMode a, OpenMode b)
-        {
-            return static_cast<OpenMode>(static_cast<AZ::u32>(a) | static_cast<AZ::u32>(b));
-        }
-
-        inline OpenMode operator & (OpenMode a, OpenMode b)
-        {
-            return static_cast<OpenMode>(static_cast<AZ::u32>(a) & static_cast<AZ::u32>(b));
-        }
-
-        inline OpenMode& operator |= (OpenMode& a, OpenMode b)
-        {
-            return a = a | b;
-        }
-
-        inline OpenMode& operator &= (OpenMode& a, OpenMode b)
-        {
-            return a = a & b;
-        }
+        AZ_DEFINE_ENUM_BITWISE_OPERATORS(OpenMode)
 
 
         OpenMode GetOpenModeFromStringMode(const char* mode);
         OpenMode GetOpenModeFromStringMode(const char* mode);
 
 
@@ -250,12 +232,14 @@ namespace AZ
             virtual bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const = 0;
             virtual bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const = 0;
             AZStd::optional<AZ::IO::FixedMaxPath> ConvertToAlias(const AZ::IO::PathView& path) const;
             AZStd::optional<AZ::IO::FixedMaxPath> ConvertToAlias(const AZ::IO::PathView& path) const;
 
 
-            /// ResolvePath - Replaces any aliases in path with their values and stores the result in resolvedPath,
-            /// also ensures that the path is absolute
-            /// returns true if path was resolved, false otherwise
-            /// note that all of the above file-finding and opening functions automatically resolve the path before operating
-            /// so you should not need to call this except in very exceptional circumstances where you absolutely need to
-            /// hit a physical file and don't want to use SystemFile
+            //! ResolvePath - Replaces any aliases in path with their values and stores the result in resolvedPath,
+            //! also ensures that the path is absolute
+            //! NOTE: If the path does not start with an alias then the resolved value of the @assets@ is used
+            //!       which has the effect of making the path relative to the @assets@/ folder
+            //! returns true if path was resolved, false otherwise
+            //! note that all of the above file-finding and opening functions automatically resolve the path before operating
+            //! so you should not need to call this except in very exceptional circumstances where you absolutely need to
+            //! hit a physical file and don't want to use SystemFile
             virtual bool ResolvePath(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize) const = 0;
             virtual bool ResolvePath(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize) const = 0;
 
 
             //! ResolvePath - Replaces any @ aliases in the supplied path with their the resolved alias values
             //! ResolvePath - Replaces any @ aliases in the supplied path with their the resolved alias values
@@ -265,6 +249,11 @@ namespace AZ
             virtual bool ResolvePath(AZ::IO::FixedMaxPath& resolvedPath, const AZ::IO::PathView& path) const = 0;
             virtual bool ResolvePath(AZ::IO::FixedMaxPath& resolvedPath, const AZ::IO::PathView& path) const = 0;
             AZStd::optional<AZ::IO::FixedMaxPath> ResolvePath(const AZ::IO::PathView& path) const;
             AZStd::optional<AZ::IO::FixedMaxPath> ResolvePath(const AZ::IO::PathView& path) const;
 
 
+            //! ReplaceAliases - If the path starts with an @...@ alias it is substituted with the alias value
+            //! otherwise the path is copied as is to the resolvedAlias path value
+            //! returns true if the resulting path can fit within AZ::IO::FixedMaxPath buffer
+            virtual bool ReplaceAlias(AZ::IO::FixedMaxPath& replacedAliasPath, const AZ::IO::PathView& path) const = 0;
+
             /// Divulge the filename used to originally open that handle.
             /// Divulge the filename used to originally open that handle.
             virtual bool GetFilename(HandleType fileHandle, char* filename, AZ::u64 filenameSize) const = 0;
             virtual bool GetFilename(HandleType fileHandle, char* filename, AZ::u64 filenameSize) const = 0;
 
 

+ 4 - 4
Code/Framework/AzCore/AzCore/IO/Path/Path.h

@@ -170,7 +170,7 @@ namespace AZ::IO
         //! Check whether the path is not absolute
         //! Check whether the path is not absolute
         [[nodiscard]] constexpr bool IsRelative() const;
         [[nodiscard]] constexpr bool IsRelative() const;
         //! Check whether the path is relative to the base path
         //! Check whether the path is relative to the base path
-        [[nodiscard]] constexpr bool IsRelativeTo(const PathView & base) const;
+        [[nodiscard]] constexpr bool IsRelativeTo(const PathView& base) const;
 
 
         //! Normalizes a path in a purely lexical manner.
         //! Normalizes a path in a purely lexical manner.
         //! # Path separators are converted to their preferred path separator
         //! # Path separators are converted to their preferred path separator
@@ -517,7 +517,7 @@ namespace AZ::IO
         //! Checks if the path has a root directory
         //! Checks if the path has a root directory
         [[nodiscard]] constexpr bool HasRootDirectory() const;
         [[nodiscard]] constexpr bool HasRootDirectory() const;
         //! Checks whether the entire root path portion of the path is empty
         //! Checks whether the entire root path portion of the path is empty
-        //! The root portion ofthe path is made up of root_name() / root_directory()
+        //! The root portion of the path is made up of root_name() / root_directory()
         [[nodiscard]] constexpr bool HasRootPath() const;
         [[nodiscard]] constexpr bool HasRootPath() const;
         //! checks whether the relative part of path is empty
         //! checks whether the relative part of path is empty
         //! (C:\\     lumberyard\dev\)
         //! (C:\\     lumberyard\dev\)
@@ -539,8 +539,8 @@ namespace AZ::IO
         [[nodiscard]] constexpr bool IsAbsolute() const;
         [[nodiscard]] constexpr bool IsAbsolute() const;
         //! Check whether the path is not absolute
         //! Check whether the path is not absolute
         [[nodiscard]] constexpr bool IsRelative() const;
         [[nodiscard]] constexpr bool IsRelative() const;
-        //! Check whether the path is relative to the input path
-        [[nodiscard]] constexpr bool IsRelativeTo() const;
+        //! Check whether the path is relative to the base path
+        [[nodiscard]] constexpr bool IsRelativeTo(const PathView& base) const;
 
 
         // decomposition
         // decomposition
         //! Given a windows path of "C:\lumberyard\foo\bar\name.txt" and a posix path of
         //! Given a windows path of "C:\lumberyard\foo\bar\name.txt" and a posix path of

+ 3 - 3
Code/Framework/AzCore/AzCore/IO/Path/Path.inl

@@ -1035,7 +1035,7 @@ namespace AZ::IO
         // move the parser from the end to a valid filename by decrementing
         // move the parser from the end to a valid filename by decrementing
         for(--pathParserEnd, --patternParserEnd; pathParserEnd && patternParserEnd; --pathParserEnd, --patternParserEnd)
         for(--pathParserEnd, --patternParserEnd; pathParserEnd && patternParserEnd; --pathParserEnd, --patternParserEnd)
         {
         {
-            if (!AZStd::wildcard_match(*patternParserEnd, *pathParserEnd))
+            if (!AZStd::wildcard_match_case(*patternParserEnd, *pathParserEnd))
             {
             {
                 return false;
                 return false;
             }
             }
@@ -1830,9 +1830,9 @@ namespace AZ::IO
     }
     }
 
 
     template <typename StringType>
     template <typename StringType>
-    [[nodiscard]] constexpr bool BasicPath<StringType>::IsRelativeTo() const
+    [[nodiscard]] constexpr bool BasicPath<StringType>::IsRelativeTo(const PathView& base) const
     {
     {
-        return static_cast<PathView>(*this).IsRelative();
+        return static_cast<PathView>(*this).IsRelativeTo(base);
     }
     }
 
 
     template <typename StringType>
     template <typename StringType>

+ 1 - 0
Code/Framework/AzCore/AzCore/Math/MathReflection.cpp

@@ -369,6 +369,7 @@ namespace AZ
         context.Serializer<JsonVector2Serializer>()->HandlesType<Vector2>();
         context.Serializer<JsonVector2Serializer>()->HandlesType<Vector2>();
         context.Serializer<JsonVector3Serializer>()->HandlesType<Vector3>();
         context.Serializer<JsonVector3Serializer>()->HandlesType<Vector3>();
         context.Serializer<JsonVector4Serializer>()->HandlesType<Vector4>();
         context.Serializer<JsonVector4Serializer>()->HandlesType<Vector4>();
+        context.Serializer<JsonQuaternionSerializer>()->HandlesType<Quaternion>();
     }
     }
 
 
     void MathReflect(ReflectContext* context)
     void MathReflect(ReflectContext* context)

+ 53 - 0
Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp

@@ -14,6 +14,7 @@
 #include <AzCore/Math/Vector2.h>
 #include <AzCore/Math/Vector2.h>
 #include <AzCore/Math/Vector3.h>
 #include <AzCore/Math/Vector3.h>
 #include <AzCore/Math/Vector4.h>
 #include <AzCore/Math/Vector4.h>
+#include <AzCore/Math/Quaternion.h>
 #include <AzCore/Math/MathVectorSerializer.h>
 #include <AzCore/Math/MathVectorSerializer.h>
 #include <AzCore/Serialization/Json/JsonSerialization.h>
 #include <AzCore/Serialization/Json/JsonSerialization.h>
 #include <AzCore/Serialization/Json/RegistrationContext.h>
 #include <AzCore/Serialization/Json/RegistrationContext.h>
@@ -238,4 +239,56 @@ namespace AZ
     {
     {
         return JsonMathVectorSerializerInternal::Store<Vector4, 4>(outputValue, inputValue, defaultValue, valueTypeId, context);
         return JsonMathVectorSerializerInternal::Store<Vector4, 4>(outputValue, inputValue, defaultValue, valueTypeId, context);
     }
     }
+
+    // Quaternion
+
+    AZ_CLASS_ALLOCATOR_IMPL(JsonQuaternionSerializer, SystemAllocator, 0);
+
+    JsonSerializationResult::Result JsonQuaternionSerializer::Load(void* outputValue, const Uuid& outputValueTypeId,
+        const rapidjson::Value& inputValue, JsonDeserializerContext& context)
+    {
+        namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds.
+
+        // check for "yaw, pitch, roll" object
+        if (inputValue.IsObject())
+        {
+            if (inputValue.GetObject().ObjectEmpty())
+            {
+                Quaternion* outQuaternion = reinterpret_cast<Quaternion*>(outputValue);
+                *outQuaternion = Quaternion::CreateIdentity();
+                return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Using identity quaternion for empty object.");
+            }
+
+            AZ::BaseJsonSerializer* floatSerializer = context.GetRegistrationContext()->GetSerializerForType(azrtti_typeid<float>());
+            if (!floatSerializer)
+            {
+                return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic, "Failed to find the json float serializer.");
+            }
+
+            constexpr const char* names[3] = {"yaw", "pitch", "roll"};
+            float values[3];
+            int i = 0;
+            for (auto itr = inputValue.MemberBegin(); itr != inputValue.MemberEnd(); ++i, ++itr)
+            {
+                ScopedContextPath subPath(context, names[i]);
+                JSR::Result intermediate = floatSerializer->Load(values + i, azrtti_typeid<float>(), itr->value, context);
+                if (intermediate.GetResultCode().GetProcessing() != JSR::Processing::Completed)
+                {
+                    return intermediate;
+                }
+            }
+
+            auto eulerAnglesDegrees = Vector3::CreateFromFloat3(values);
+            reinterpret_cast<Quaternion*>(outputValue)->SetFromEulerDegrees(eulerAnglesDegrees);
+            return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success, "Successfully read quaternion.");
+        }
+
+        return JsonMathVectorSerializerInternal::Load<Quaternion, 4>(outputValue, outputValueTypeId, inputValue, context);
+    }
+
+    JsonSerializationResult::Result JsonQuaternionSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
+        const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context)
+    {
+        return JsonMathVectorSerializerInternal::Store<Quaternion, 4>(outputValue, inputValue, defaultValue, valueTypeId, context);
+    }
 }
 }

+ 12 - 0
Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.h

@@ -51,4 +51,16 @@ namespace AZ
         JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
         JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
             const Uuid& valueTypeId, JsonSerializerContext& context) override;
             const Uuid& valueTypeId, JsonSerializerContext& context) override;
     };
     };
+
+    class JsonQuaternionSerializer
+        : public BaseJsonSerializer
+    {
+    public:
+        AZ_RTTI(JsonQuaternionSerializer, "{18604375-3606-49AC-B366-0F6DF9149FF3}", BaseJsonSerializer);
+        AZ_CLASS_ALLOCATOR_DECL;
+        JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
+            JsonDeserializerContext& context) override;
+        JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
+            const Uuid& valueTypeId, JsonSerializerContext& context) override;
+    };
 }
 }

+ 186 - 122
Code/Framework/AzCore/AzCore/Settings/CommandLine.cpp

@@ -10,11 +10,11 @@
 *
 *
 */
 */
 
 
-#include <AzCore/Settings/CommandLine.h>
+#include <AzCore/AzCore_Traits_Platform.h>
+#include <AzCore/std/functional.h>
 #include <AzCore/std/string/conversions.h>
 #include <AzCore/std/string/conversions.h>
+#include <AzCore/Settings/CommandLine.h>
 #include <AzCore/StringFunc/StringFunc.h>
 #include <AzCore/StringFunc/StringFunc.h>
-#include <AzCore/AzCore_Traits_Platform.h>
-#include <AzCore/std/tuple.h>
 
 
 namespace AZ
 namespace AZ
 {
 {
@@ -29,6 +29,21 @@ namespace AZ
 
 
             return lowerStr;
             return lowerStr;
         }
         }
+
+        AZStd::string_view UnquoteArgument(AZStd::string_view arg)
+        {
+            if (arg.size() < 2)
+            {
+                return arg;
+            }
+
+            return arg.front() == '"' && arg.back() == '"' ? AZStd::string_view{ arg.begin() + 1, arg.end() - 1 } : arg;
+        }
+
+        AZStd::string QuoteArgument(AZStd::string_view arg)
+        {
+            return !arg.empty() ? AZStd::string::format(R"("%.*s")", aznumeric_cast<int>(arg.size()), arg.data()) : AZStd::string{ arg };
+        }
     }
     }
 
 
     CommandLine::CommandLine()
     CommandLine::CommandLine()
@@ -41,15 +56,62 @@ namespace AZ
     {
     {
     }
     }
 
 
-    void CommandLine::AddArgument(AZStd::string currentArg, AZStd::string& currentSwitch)
+    void CommandLine::ParseOptionArgument(AZStd::string_view newOption, AZStd::string_view newValue,
+        CommandArgument* inProgressArgument)
+    {
+        // Allow argument values wrapped in quotes at both ends to become the value within the quotes
+        AZStd::string_view unquotedValue = UnquoteArgument(newValue);
+        if (unquotedValue != newValue)
+        {
+            // Update the inProgressArgument before adding new arguments
+            if(inProgressArgument)
+            {
+                inProgressArgument->m_value = unquotedValue;
+                // Set the inProgressArgument to nullptr to indicate that the inProgressArgument has been fulfilled
+                inProgressArgument = nullptr;
+            }
+            else
+            {
+                m_allValues.push_back({ newOption, unquotedValue });
+            }
+        }
+        else
+        {
+            AZStd::vector<AZStd::string_view> tokens;
+            auto splitArgument = [&tokens](AZStd::string_view token)
+            {
+                tokens.emplace_back(AZ::StringFunc::StripEnds(token));
+            };
+            AZ::StringFunc::TokenizeVisitor(newValue, splitArgument, ",;");
+
+            // we do it this way because you are allowed to do odd things like
+            // -root=abc -root=hij,klm -root whee -root fun;days
+            // and roots value should be { abc, hij, klm, whee, fun, days }
+            for (AZStd::string_view optionValue : tokens)
+            {
+                if (inProgressArgument)
+                {
+                    inProgressArgument->m_value = optionValue;
+                    // Set the inProgressArgument to nullptr to indicate that the inProgressArgument has been fulfilled
+                    inProgressArgument = nullptr;
+                }
+                else
+                {
+                    m_allValues.push_back({ newOption, optionValue });
+                }
+            }
+        }
+    }
+
+    void CommandLine::AddArgument(AZStd::string_view currentArg, AZStd::string& currentSwitch)
     {
     {
-        StringFunc::Strip(currentArg, " ", false, true, true);
+        currentArg = AZ::StringFunc::StripEnds(currentArg);
         if (!currentArg.empty())
         if (!currentArg.empty())
         {
         {
-            if (AZStd::string_view(currentArg.begin(), currentArg.begin() + 1).find_first_of(m_commandLineOptionPrefix) != AZStd::string_view::npos)
+            if (m_commandLineOptionPrefix.contains(currentArg.front()))
             {
             {
-                // its possible that its a key-value-pair like /blah=whatever
-                // we support this too, for compatibilty.
+                // its possible that its a key-value-pair like -blah=whatever
+                // we support this too, for compatibility.
 
 
                 currentArg = currentArg.substr(1);
                 currentArg = currentArg.substr(1);
                 if (currentArg[0] == '-') // for -- extra
                 if (currentArg[0] == '-') // for -- extra
@@ -57,93 +119,41 @@ namespace AZ
                     currentArg = currentArg.substr(1);
                     currentArg = currentArg.substr(1);
                 }
                 }
 
 
-                AZStd::size_t foundPos = StringFunc::Find(currentArg.c_str(), '=');
+                AZStd::size_t foundPos = AZ::StringFunc::Find(currentArg, "=");
                 if (foundPos != AZStd::string::npos)
                 if (foundPos != AZStd::string::npos)
                 {
                 {
-                    // Allow argument values wrapped in quotes at both ends to become the value within the quotes 
-                    if (currentArg.length() > (foundPos + 2) && currentArg[foundPos + 1] == '"' && currentArg[currentArg.length() - 1] == '"')
-                    {
-                        AZStd::string argName = currentArg.substr(0, foundPos);
-                        argName = ToLower(argName);
-                        StringFunc::Strip(argName, " ", false, true, true);
-                        m_switches[argName].emplace_back(currentArg.substr(foundPos + 2, currentArg.length() - (foundPos + 2) - 1));
-                        currentSwitch.clear();
-                        return;
-                    }
-
-                    // its in '=' format
-                    AZStd::vector<AZStd::string> tokens;
-                    StringFunc::Tokenize(currentArg.substr(foundPos + 1).c_str(), tokens, ",;");
-                    currentArg.resize(foundPos);
-                    currentArg = ToLower(currentArg);
-                    StringFunc::Strip(currentArg, " ", false, true, true);
-                    m_switches.insert_key(currentArg); // returns pair<iter, bool>
-                   // we do it this way because you are allowed to do odd things like
-                   // /root=abc /root=hij,klm /root whee /root fun;days
-                   // and roots value should be { abc, hij, klm, whee, fun, days }
-                    for (AZStd::string& switchValue : tokens)
-                    {
-                        StringFunc::Strip(switchValue, " ", false, true, true);
-                        m_switches[currentArg].push_back(switchValue);
-                    }
+                    AZStd::string_view argumentView{ currentArg };
+                    AZStd::string_view option = AZ::StringFunc::StripEnds(argumentView.substr(0, foundPos));
+                    AZStd::string_view value = AZ::StringFunc::StripEnds(argumentView.substr(foundPos + 1));
+                    ParseOptionArgument(ToLower(option), value, nullptr);
                     currentSwitch.clear();
                     currentSwitch.clear();
                 }
                 }
                 else
                 else
                 {
                 {
-                    // its in this format /switchName switchvalue
+                    // its in this format -switchName switchvalue
                     // (no equals)
                     // (no equals)
-                    currentSwitch = currentArg;
-                    currentSwitch = ToLower(currentSwitch);
-                    m_switches.insert_key(currentSwitch);
+                    currentSwitch = ToLower(currentArg);
+                    m_allValues.push_back({ currentSwitch, "" });
                 }
                 }
             }
             }
             else
             else
             {
             {
                 if (currentSwitch.empty())
                 if (currentSwitch.empty())
                 {
                 {
-                    m_miscValues.push_back(currentArg);
+                    m_allValues.push_back({ "", UnquoteArgument(currentArg) });
                 }
                 }
                 else
                 else
                 {
                 {
-                    // Allow argument values wrapped in quotes at both ends to become the value within the quotes
-                    if (currentArg[0] == '"' && currentArg.length() >= 2 && currentArg[currentArg.length() - 1] == '"')
-                    {
-                        m_switches[currentSwitch].emplace_back(currentArg.substr(1, currentArg.length() - 2));
-                        currentSwitch.clear();
-                        return;
-                    }
-
-                    AZStd::vector<AZStd::string> tokens;
-                    StringFunc::Tokenize(currentArg.c_str(), tokens, ",;");
-                    for (AZStd::string& switchValue : tokens)
-                    {
-                        StringFunc::Strip(switchValue, " ", false, true, true);
-                        m_switches[currentSwitch].push_back(switchValue);
-                    }
-
+                    ParseOptionArgument(currentSwitch, currentArg, &m_allValues.back());
+                    currentSwitch.clear();
                 }
                 }
-
-                currentSwitch.clear();
             }
             }
         }
         }
     }
     }
 
 
-    void CommandLine::Parse(const ParamContainer& commandLine)
-    {
-        m_switches.clear();
-        m_miscValues.clear();
-
-        AZStd::string currentSwitch;
-        for (int i = 1; i < commandLine.size(); ++i)
-        {
-            AddArgument(commandLine[i], currentSwitch);
-        }
-    }
-
     void CommandLine::Parse(int argc, char** argv)
     void CommandLine::Parse(int argc, char** argv)
     {
     {
-        m_switches.clear();
-        m_miscValues.clear();
+        m_allValues.clear();
 
 
         AZStd::string currentSwitch;
         AZStd::string currentSwitch;
         // Start on 1 because 0 is the executable name
         // Start on 1 because 0 is the executable name
@@ -157,91 +167,145 @@ namespace AZ
         }
         }
     }
     }
 
 
-    void CommandLine::Dump(ParamContainer& commandLineDumpOutput)
+    void CommandLine::Parse(const ParamContainer& commandLine)
     {
     {
-        // Push back an empty argument as the Parse function always skips parsing the first argument
-        commandLineDumpOutput.emplace_back(AZStd::string());
-        for (const AZStd::string& miscValue : m_miscValues)
+        m_allValues.clear();
+
+        // This version of Parse does not skip over 0th index
+        AZStd::string currentSwitch;
+        for (int i = 0; i < commandLine.size(); ++i)
         {
         {
-            commandLineDumpOutput.push_back(miscValue);
+            AddArgument(commandLine[i], currentSwitch);
         }
         }
+    }
+
+    void CommandLine::Dump(ParamContainer& commandLineDumpOutput) const
+    {
+        AZ_Error("CommandLine", !m_commandLineOptionPrefix.empty(),
+            "Cannot dump command line switches from a command line with an empty option prefix");
 
 
-        if (!m_commandLineOptionPrefix.empty())
+        for (const CommandArgument& argument : m_allValues)
         {
         {
-            for (const auto& [switchKey, switchValues] : m_switches)
+            if (!argument.m_option.empty())
             {
             {
-                AZStd::string prefixSwitchKey = m_commandLineOptionPrefix.front() + switchKey;
-                if (switchValues.empty())
-                {
-                    // There are no value for the switch so just push it back of the command line dump output
-                    commandLineDumpOutput.emplace_back(prefixSwitchKey);
-                }
-                else
-                {
-                    for (const auto& switchValue : switchValues)
-                    {
-                        commandLineDumpOutput.emplace_back(prefixSwitchKey);
-                        commandLineDumpOutput.emplace_back(switchValue);
-                    }
-                }
+                commandLineDumpOutput.emplace_back(m_commandLineOptionPrefix.front() + argument.m_option);
+            }
+            if (!argument.m_value.empty())
+            {
+                commandLineDumpOutput.emplace_back(QuoteArgument(argument.m_value));
             }
             }
-        }
-        else
-        {
-            AZ_Error("CommandLine", false, "Cannot dump command line switches from a command line with an empty option prefix");
         }
         }
     }
     }
 
 
     bool CommandLine::HasSwitch(AZStd::string_view switchName) const
     bool CommandLine::HasSwitch(AZStd::string_view switchName) const
     {
     {
-        return m_switches.find(ToLower(switchName)) != m_switches.end();
+        auto commandArgumentIter = AZStd::find_if(m_allValues.begin(), m_allValues.end(),
+            [optionName = ToLower(switchName)](const CommandArgument& argument) { return argument.m_option == optionName; });
+        return commandArgumentIter != m_allValues.end();
     }
     }
 
 
     AZStd::size_t CommandLine::GetNumSwitchValues(AZStd::string_view switchName) const
     AZStd::size_t CommandLine::GetNumSwitchValues(AZStd::string_view switchName) const
     {
     {
-        ParamMap::const_iterator switchFound = m_switches.find(ToLower(switchName));
-        if (switchFound == m_switches.end())
-        {
-            return 0;
-        }
-
-        return switchFound->second.size();
+        return AZStd::count_if(m_allValues.begin(), m_allValues.end(),
+            [optionName = ToLower(switchName)](const CommandArgument& argument) { return argument.m_option == optionName; });
     }
     }
 
 
     const AZStd::string& CommandLine::GetSwitchValue(AZStd::string_view switchName, AZStd::size_t index) const
     const AZStd::string& CommandLine::GetSwitchValue(AZStd::string_view switchName, AZStd::size_t index) const
     {
     {
-        ParamMap::const_iterator switchFound = m_switches.find(ToLower(switchName));
-        if (switchFound == m_switches.end())
+        AZStd::string optionName = ToLower(switchName);
+        size_t currentPosIndex{};
+        auto findArgumentAt = [&optionName, index, &currentPosIndex](const CommandArgument& argument)
         {
         {
-            return m_emptyValue;
-        }
+            if (argument.m_option == optionName)
+            {
+                return currentPosIndex++ == index;
+            }
 
 
-        AZ_Assert(index < switchFound->second.size(), "Invalid Command line switch lookup");
-        if (index >= switchFound->second.size())
+            return false;
+        };
+        auto commandArgumentIter = AZStd::find_if(m_allValues.begin(), m_allValues.end(), findArgumentAt);
+        if (!optionName.empty())
+        {
+            AZ_Assert(index < currentPosIndex, R"(Invalid Command line optional argument lookup of "%s" at index %zu)",
+                optionName.c_str(), index);
+        }
+        else
+        {
+            AZ_Assert(index < currentPosIndex, R"(Invalid Command line positional argument lookup at index %zu)", index);
+        }
+        if (commandArgumentIter == m_allValues.end())
         {
         {
             return m_emptyValue;
             return m_emptyValue;
         }
         }
-
-        return switchFound->second.at(index);
+        return commandArgumentIter->m_value;
     }
     }
 
 
     AZStd::size_t CommandLine::GetNumMiscValues() const
     AZStd::size_t CommandLine::GetNumMiscValues() const
     {
     {
-        return m_miscValues.size();
+        return GetNumSwitchValues("");
     }
     }
 
 
     const AZStd::string& CommandLine::GetMiscValue(AZStd::size_t index) const
     const AZStd::string& CommandLine::GetMiscValue(AZStd::size_t index) const
     {
     {
-        AZ_Assert(index < m_miscValues.size(), "Invalid Command line lookup");
-        if (index >= m_miscValues.size())
-        {
-            return m_emptyValue;
-        }
-        return m_miscValues[index];
+        // Positional arguments option value is an empty string
+        return GetSwitchValue("", index);
     }
     }
 
 
-    const CommandLine::ParamMap& CommandLine::GetSwitchList() const
+    [[nodiscard]] bool CommandLine::empty() const
+    {
+        return m_allValues.empty();
+    }
+
+    auto CommandLine::size() const -> ArgumentVector::size_type
+    {
+        return m_allValues.size();
+    }
+    auto CommandLine::begin() -> ArgumentVector::iterator
+    {
+        return m_allValues.begin();
+    }
+    auto CommandLine::begin() const -> ArgumentVector::const_iterator
+    {
+        return m_allValues.begin();
+    }
+    auto CommandLine::cbegin() const -> ArgumentVector::const_iterator
+    {
+        return m_allValues.cbegin();
+    }
+    auto CommandLine::end() -> ArgumentVector::iterator
+    {
+        return m_allValues.end();
+    }
+    auto CommandLine::end() const -> ArgumentVector::const_iterator
+    {
+        return m_allValues.end();
+    }
+    auto CommandLine::cend() const -> ArgumentVector::const_iterator
+    {
+        return m_allValues.cend();
+    }
+    auto CommandLine::rbegin() -> ArgumentVector::reverse_iterator
+    {
+        return m_allValues.rbegin();
+    }
+    auto CommandLine::rbegin() const -> ArgumentVector::const_reverse_iterator
+    {
+        return m_allValues.rbegin();
+    }
+    auto CommandLine::crbegin() const -> ArgumentVector::const_reverse_iterator
+    {
+        return m_allValues.crbegin();
+    }
+    auto CommandLine::rend() -> ArgumentVector::reverse_iterator
+    {
+        return m_allValues.rend();
+    }
+    auto CommandLine::rend() const -> ArgumentVector::const_reverse_iterator
+    {
+        return m_allValues.rend();
+    }
+    auto CommandLine::crend() const -> ArgumentVector::const_reverse_iterator
     {
     {
-        return m_switches;
+        return m_allValues.crend();
     }
     }
 }
 }

+ 37 - 14
Code/Framework/AzCore/AzCore/Settings/CommandLine.h

@@ -36,36 +36,47 @@ namespace AZ
     public:
     public:
         AZ_CLASS_ALLOCATOR(CommandLine, AZ::SystemAllocator, 0);
         AZ_CLASS_ALLOCATOR(CommandLine, AZ::SystemAllocator, 0);
 
 
+        using ParamContainer = AZStd::vector<AZStd::string>;
+
+        struct CommandArgument
+        {
+            AZStd::string m_option;
+            AZStd::string m_value;
+        };
+        using ArgumentVector = AZStd::vector<CommandArgument>;
+
         CommandLine();
         CommandLine();
 
 
         /**
         /**
          * Initializes a CommandLine instance which uses the provided commandLineOptionPreix for parsing switches
          * Initializes a CommandLine instance which uses the provided commandLineOptionPreix for parsing switches
          */
          */
         CommandLine(AZStd::string_view commandLineOptionPrefix);
         CommandLine(AZStd::string_view commandLineOptionPrefix);
-
-        using ParamContainer = AZStd::vector<AZStd::string>;
-        using ParamMap = AZStd::unordered_map<AZStd::string, ParamContainer>;
         /**
         /**
         * Construct a command line parser.
         * Construct a command line parser.
         * It will load parameters from the given ARGC/ARGV parameters instead of process command line.
         * It will load parameters from the given ARGC/ARGV parameters instead of process command line.
+        * Skips over the first parameter as it assumes it is the executable name
         */
         */
         void Parse(int argc, char** argv);
         void Parse(int argc, char** argv);
+        /**
+         * Parses each element of the command line as parameter.
+         * Unlike the ARGC/ARGV version above, this function doesn't skip over the first parameter
+         * It allows for round trip conversion with the Dump() method
+         */
         void Parse(const ParamContainer& commandLine);
         void Parse(const ParamContainer& commandLine);
 
 
         /**
         /**
         * Will dump command line parameters from the CommandLine in a format such that switches
         * Will dump command line parameters from the CommandLine in a format such that switches
         * are prefixed with the option prefix followed by their value(s) which are comma separated
         * are prefixed with the option prefix followed by their value(s) which are comma separated
-        * The result of this function can be supplied to Parse() to re-create an eqiuvlanet command line obect
+        * The result of this function can be supplied to Parse() to re-create an equivalent command line object
         * Ex, If the command line has the current list of parsed miscellaneous values and switches of
         * Ex, If the command line has the current list of parsed miscellaneous values and switches of
         * MiscValue = ["Foo", "Bat"]
         * MiscValue = ["Foo", "Bat"]
         * Switches = ["GameFolder" : [], "RemoteIp" : ["10.0.0.1"], "ScanFolders" : ["\a\b\c", "\d\e\f"]
         * Switches = ["GameFolder" : [], "RemoteIp" : ["10.0.0.1"], "ScanFolders" : ["\a\b\c", "\d\e\f"]
         * CommandLineOptionPrefix = "-/"
         * CommandLineOptionPrefix = "-/"
         *
         *
         * Then the resulting dumped value would be
         * Then the resulting dumped value would be
-        * Dump = ["", "Foo", "Bat", "-GameFolder", "-RemoteIp", "10.0.0.1", "-ScanFolders", "\a\b\c", "-ScanFolders", "\d\e\f"]
-        * NOTE: The first parameter is always empty string as the Parse function skips over it
+        * Dump = ["Foo", "Bat", "-GameFolder", "-RemoteIp", "10.0.0.1", "-ScanFolders", "\a\b\c", "-ScanFolders", "\d\e\f"]
         */
         */
-        void Dump(ParamContainer& commandLineDumpOutput);
+        void Dump(ParamContainer& commandLineDumpOutput) const;
 
 
         /**
         /**
         * Determines whether a switch is present in the command line
         * Determines whether a switch is present in the command line
@@ -97,16 +108,28 @@ namespace AZ
         */
         */
         const AZStd::string& GetMiscValue(AZStd::size_t index) const;
         const AZStd::string& GetMiscValue(AZStd::size_t index) const;
 
 
-        /*
-        * Return the list of parsed switches
-        */
-        const ParamMap& GetSwitchList() const;
+
+        // Range accessors
+        [[nodiscard]] bool empty() const;
+        auto size() const -> ArgumentVector::size_type;
+        auto begin() -> ArgumentVector::iterator;
+        auto begin() const -> ArgumentVector::const_iterator;
+        auto cbegin() const -> ArgumentVector::const_iterator;
+        auto end() -> ArgumentVector::iterator;
+        auto end() const -> ArgumentVector::const_iterator;
+        auto cend() const -> ArgumentVector::const_iterator;
+        auto rbegin() -> ArgumentVector::reverse_iterator;
+        auto rbegin() const -> ArgumentVector::const_reverse_iterator;
+        auto crbegin() const -> ArgumentVector::const_reverse_iterator;
+        auto rend() -> ArgumentVector::reverse_iterator;
+        auto rend() const -> ArgumentVector::const_reverse_iterator;
+        auto crend() const -> ArgumentVector::const_reverse_iterator;
 
 
     private:
     private:
-        void AddArgument(AZStd::string currentArg, AZStd::string& currentSwitch);
+        void AddArgument(AZStd::string_view currentArg, AZStd::string& currentSwitch);
+        void ParseOptionArgument(AZStd::string_view newOption, AZStd::string_view newValue, CommandArgument* inProgressArgument);
 
 
-        ParamMap m_switches;
-        ParamContainer m_miscValues;
+        ArgumentVector m_allValues;
         AZStd::string m_emptyValue;
         AZStd::string m_emptyValue;
 
 
         inline static constexpr size_t MaxCommandOptionPrefixes = 8;
         inline static constexpr size_t MaxCommandOptionPrefixes = 8;

+ 9 - 1
Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp

@@ -173,7 +173,15 @@ namespace AZ
                     path.remove_prefix(1); // Remove the leading slash as the StackedString will add this back in.
                     path.remove_prefix(1); // Remove the leading slash as the StackedString will add this back in.
                     jsonPath.Push(path);
                     jsonPath.Push(path);
                 }
                 }
-                Visit(visitor, jsonPath, "", *value);
+                // Extract the last token of the JSON pointer to use as the valueName
+                AZStd::string_view valueName;
+                size_t pointerTokenCount = pointer.GetTokenCount();
+                if (pointerTokenCount > 0)
+                {
+                    const rapidjson::Pointer::Token& lastToken = pointer.GetTokens()[pointerTokenCount - 1];
+                    valueName = AZStd::string_view(lastToken.name, lastToken.length);
+                }
+                Visit(visitor, jsonPath, valueName, *value);
                 return true;
                 return true;
             }
             }
         }
         }

+ 400 - 229
Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp

@@ -41,68 +41,197 @@ namespace AZ::Internal
 
 
         return value;
         return value;
     }
     }
-}
 
 
-namespace AZ::SettingsRegistryMergeUtils
-{
-    AZ::IO::FixedMaxPath GetAppRoot(SettingsRegistryInterface* settingsRegistry)
+    AZ::SettingsRegistryInterface::FixedValueString GetEngineMonikerForProject(
+        SettingsRegistryInterface& settingsRegistry, const AZ::IO::FixedMaxPath& projectPath)
     {
     {
-        constexpr size_t MaxAppRootPathsToScan = 16;
-        AZStd::fixed_vector<AZStd::string_view, MaxAppRootPathsToScan> appRootScanPaths;
-
-        // Check the commandLine for --app-root parameter
-        // If it exist use that instead
-        auto appRootOverrideKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/app-root", AZ::SettingsRegistryMergeUtils::CommandLineSwitchRootKey);
-        if (settingsRegistry)
+        // projectPath needs to be an absolute path here.
+        using namespace AZ::SettingsRegistryMergeUtils;
+        bool projectJsonMerged = false;
+        auto projectJsonPath = projectPath / "project.json";
+        if (AZ::IO::SystemFile::Exists(projectJsonPath.c_str()))
         {
         {
-            AZ::IO::FixedMaxPath appRootOverridePath;
-            if (settingsRegistry->Get(appRootOverridePath.Native(), appRootOverrideKey))
-            {
-                return appRootOverridePath;
-            }
+            projectJsonMerged = settingsRegistry.MergeSettingsFile(
+                projectJsonPath.Native(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, ProjectSettingsRootKey);
         }
         }
 
 
-        AZStd::optional<AZStd::fixed_string<AZ::IO::MaxPathLength>> appRootPath = Utils::GetDefaultAppRootPath();
-        if (appRootPath.has_value())
+        AZ::SettingsRegistryInterface::FixedValueString engineMoniker;
+        if (projectJsonMerged)
         {
         {
-            appRootScanPaths.push_back(*appRootPath);
+            // In project.json look for the "engine" key.
+            auto engineMonikerKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/engine", ProjectSettingsRootKey);
+            settingsRegistry.Get(engineMoniker, engineMonikerKey);
         }
         }
-        AZStd::fixed_string<AZ::IO::MaxPathLength> executableDir;
-        AZ::Utils::ExecutablePathResult pathResult = Utils::GetExecutableDirectory(executableDir.data(), executableDir.capacity());
-        if (pathResult == Utils::ExecutablePathResult::Success)
+
+        return engineMoniker;
+    }
+
+    AZ::IO::FixedMaxPath ReconcileEngineRootFromProjectPath(SettingsRegistryInterface& settingsRegistry, const AZ::IO::FixedMaxPath& projectPath)
+    {
+        // Find the engine root via the engine manifest file and project.json
+        // Locate the engine manifest file and merge it to settings registry.
+        // Visit over the engine paths list and merge the engine.json files to settings registry.
+        // Merge project.json to settings registry.  That will give us an "engine" key.
+        // When we find a match for "engine_name" value against the "engine" value from before, we can stop and use that engine root.
+        // Finally set the BootstrapSettingsRootKey/engine_path setting so that subsequent calls to GetEngineRoot will use that
+        // and avoid all this logic.
+
+        using namespace AZ::SettingsRegistryMergeUtils;
+
+        AZ::IO::FixedMaxPath engineRoot;
+        if (auto engineManifestPath = AZ::Utils::GetEngineManifestPath(); !engineManifestPath.empty())
         {
         {
-            // Update the size value of the executable directory fixed string to correctly be the length of the null-terminated string stored within it
-            executableDir.resize_no_construct(AZStd::char_traits<char>::length(executableDir.data()));
-            if (auto foundIt = AZStd::find(appRootScanPaths.begin(), appRootScanPaths.end(), executableDir);
-                foundIt == appRootScanPaths.end())
+            bool manifestLoaded{false};
+
+            if (AZ::IO::SystemFile::Exists(engineManifestPath.c_str()))
             {
             {
-                appRootScanPaths.push_back(executableDir);
+                manifestLoaded = settingsRegistry.MergeSettingsFile(
+                    engineManifestPath, AZ::SettingsRegistryInterface::Format::JsonMergePatch, EngineManifestRootKey);
             }
             }
-        }
-        for (AZStd::string_view appRootScanPath : appRootScanPaths)
-        {
-            AZ::IO::FixedMaxPath appRootCandidate{ appRootScanPath };
 
 
-            // Search for the application root
-            bool rootPathVisited = false;
-            do
+            struct EngineInfo
+            {
+                AZ::IO::FixedMaxPath m_path;
+                AZ::SettingsRegistryInterface::FixedValueString m_moniker;
+            };
+
+            struct EnginePathsVisitor : public AZ::SettingsRegistryInterface::Visitor
             {
             {
-                if (AZ::IO::SystemFile::Exists((appRootCandidate / "bootstrap.cfg").c_str()))
+                void Visit(
+                    [[maybe_unused]] AZStd::string_view path, [[maybe_unused]] AZStd::string_view valueName,
+                    [[maybe_unused]] AZ::SettingsRegistryInterface::Type type, AZStd::string_view value) override
                 {
                 {
-                    return appRootCandidate;
+                    m_enginePaths.emplace_back(EngineInfo{AZ::IO::FixedMaxPath{value}.LexicallyNormal(), {}});
                 }
                 }
 
 
-                // Validate that the parent directory isn't itself, that would imply
-                // that it is the root path
-                AZ::IO::PathView parentPath = appRootCandidate.ParentPath();
-                rootPathVisited = appRootCandidate == parentPath;
-                // Recurse upwards one directory
-                appRootCandidate = AZStd::move(parentPath);
+                AZStd::vector<EngineInfo> m_enginePaths{};
+            };
+
+            EnginePathsVisitor pathVisitor;
+            if (manifestLoaded)
+            {
+                auto enginePathsKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/engines", EngineManifestRootKey);
+                settingsRegistry.Visit(pathVisitor, enginePathsKey);
+            }
+
+            const auto engineMonikerKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/engine_name", EngineSettingsRootKey);
+
+            for (EngineInfo& engineInfo : pathVisitor.m_enginePaths)
+            {
+                AZ::IO::FixedMaxPath engineSettingsPath{engineInfo.m_path};
+                engineSettingsPath /= "engine.json";
+
+                if (AZ::IO::SystemFile::Exists(engineSettingsPath.c_str()))
+                {
+                    if (settingsRegistry.MergeSettingsFile(
+                            engineSettingsPath.Native(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, EngineSettingsRootKey))
+                    {
+                        settingsRegistry.Get(engineInfo.m_moniker, engineMonikerKey);
+                    }
+                }
+
+                auto engineMoniker = Internal::GetEngineMonikerForProject(settingsRegistry, engineInfo.m_path / projectPath);
+                if (!engineMoniker.empty() && engineMoniker == engineInfo.m_moniker)
+                {
+                    engineRoot = engineInfo.m_path;
+                    break;
+                }
+            }
+        }
+
+        return engineRoot;
+    }
+
+    AZ::IO::FixedMaxPath ScanUpRootLocator(AZStd::string_view rootFileToLocate)
+    {
+
+        AZStd::fixed_string<AZ::IO::MaxPathLength> executableDir;
+        if (Utils::GetExecutableDirectory(executableDir.data(), executableDir.capacity()) == Utils::ExecutablePathResult::Success)
+        {
+            // Update the size value of the executable directory fixed string to correctly be the length of the null-terminated string
+            // stored within it
+            executableDir.resize_no_construct(AZStd::char_traits<char>::length(executableDir.data()));
+        }
+
+        AZ::IO::FixedMaxPath engineRootCandidate{ executableDir };
+
+        bool rootPathVisited = false;
+        do
+        {
+            if (AZ::IO::SystemFile::Exists((engineRootCandidate / rootFileToLocate).c_str()))
+            {
+                return engineRootCandidate;
+            }
 
 
-            } while (!rootPathVisited);
             // Note for posix filesystems the parent directory of '/' is '/' and for windows
             // Note for posix filesystems the parent directory of '/' is '/' and for windows
             // the parent directory of 'C:\\' is 'C:\\'
             // the parent directory of 'C:\\' is 'C:\\'
+
+            // Validate that the parent directory isn't itself, that would imply
+            // that it is the filesystem root path
+            AZ::IO::PathView parentPath = engineRootCandidate.ParentPath();
+            rootPathVisited = (engineRootCandidate == parentPath);
+            // Recurse upwards one directory
+            engineRootCandidate = AZStd::move(parentPath);
+
+        } while (!rootPathVisited);
+
+        return {};
+    }
+
+} // namespace AZ::Internal
+
+namespace AZ::SettingsRegistryMergeUtils
+{
+    AZ::IO::FixedMaxPath FindEngineRoot(SettingsRegistryInterface& settingsRegistry)
+    {
+        AZ::IO::FixedMaxPath engineRoot;
+
+        // This is the 'external' engine root key, as in passed from command-line or .setreg files.
+        auto engineRootKey = SettingsRegistryInterface::FixedValueString::format("%s/engine_path", BootstrapSettingsRootKey);
+        if (settingsRegistry.Get(engineRoot.Native(), engineRootKey); !engineRoot.empty())
+        {
+            return engineRoot;
         }
         }
+
+        // We can scan up from exe directory to find engine.json, use that for engine root if it exists.
+        if (engineRoot = Internal::ScanUpRootLocator("engine.json"); !engineRoot.empty())
+        {
+            settingsRegistry.Set(engineRootKey, engineRoot.c_str());
+            return engineRoot;
+        }
+
+        AZ::IO::FixedMaxPath projectRoot = FindProjectRoot(settingsRegistry);
+        if (projectRoot.empty())
+        {
+            return {};
+        }
+
+        // Use the project.json and engine manifest to locate the engine root.
+        if (engineRoot = Internal::ReconcileEngineRootFromProjectPath(settingsRegistry, projectRoot); !engineRoot.empty())
+        {
+            settingsRegistry.Set(engineRootKey, engineRoot.c_str());
+            return engineRoot;
+        }
+
+        return {};
+    }
+
+    AZ::IO::FixedMaxPath FindProjectRoot(SettingsRegistryInterface& settingsRegistry)
+    {
+        AZ::IO::FixedMaxPath projectRoot;
+        // This is the 'external' project root key, as in passed from command-line or .setreg files.
+        auto projectRootKey = SettingsRegistryInterface::FixedValueString::format("%s/project_path", BootstrapSettingsRootKey);
+        if (settingsRegistry.Get(projectRoot.Native(), projectRootKey))
+        {
+            return projectRoot;
+        }
+
+        if (projectRoot = Internal::ScanUpRootLocator("project.json"); !projectRoot.empty())
+        {
+            settingsRegistry.Set(projectRootKey, projectRoot.c_str());
+            return projectRoot;
+        }
+
         return {};
         return {};
     }
     }
 
 
@@ -111,9 +240,9 @@ namespace AZ::SettingsRegistryMergeUtils
         constexpr AZStd::string_view commentPrefixes = ";#";
         constexpr AZStd::string_view commentPrefixes = ";#";
         for (char commentPrefix : commentPrefixes)
         for (char commentPrefix : commentPrefixes)
         {
         {
-            if (line.starts_with(commentPrefix))
+            if (size_t commentOffset = line.find(commentPrefix); commentOffset != AZStd::string_view::npos)
             {
             {
-                return {};
+                return line.substr(0, commentOffset);
             }
             }
         }
         }
 
 
@@ -123,7 +252,7 @@ namespace AZ::SettingsRegistryMergeUtils
     AZStd::string_view ConfigParserSettings::DefaultSectionHeaderFilter(AZStd::string_view line)
     AZStd::string_view ConfigParserSettings::DefaultSectionHeaderFilter(AZStd::string_view line)
     {
     {
         AZStd::string_view sectionName;
         AZStd::string_view sectionName;
-        constexpr char sectionHeaderStart= '[';
+        constexpr char sectionHeaderStart = '[';
         constexpr char sectionHeaderEnd = ']';
         constexpr char sectionHeaderEnd = ']';
         if (line.starts_with(sectionHeaderStart) && line.ends_with(sectionHeaderEnd))
         if (line.starts_with(sectionHeaderStart) && line.ends_with(sectionHeaderEnd))
         {
         {
@@ -184,7 +313,7 @@ namespace AZ::SettingsRegistryMergeUtils
 
 
     void QuerySpecializationsFromRegistry(SettingsRegistryInterface& registry, SettingsRegistryInterface::Specializations& specializations)
     void QuerySpecializationsFromRegistry(SettingsRegistryInterface& registry, SettingsRegistryInterface::Specializations& specializations)
     {
     {
-         // Append any specializations stored in the registry
+        // Append any specializations stored in the registry
         struct SpecializationsVisitor
         struct SpecializationsVisitor
             : AZ::SettingsRegistryInterface::Visitor
             : AZ::SettingsRegistryInterface::Visitor
         {
         {
@@ -222,7 +351,7 @@ namespace AZ::SettingsRegistryMergeUtils
     bool MergeSettingsToRegistry_ConfigFile(SettingsRegistryInterface& registry, AZStd::string_view filePath,
     bool MergeSettingsToRegistry_ConfigFile(SettingsRegistryInterface& registry, AZStd::string_view filePath,
         const ConfigParserSettings& configParserSettings)
         const ConfigParserSettings& configParserSettings)
     {
     {
-        auto configPath = GetAppRoot(&registry) / filePath;
+        auto configPath = FindEngineRoot(registry) / filePath;
         IO::SystemFile configFile;
         IO::SystemFile configFile;
         if (!configFile.Open(configPath.c_str(), IO::SystemFile::OpenMode::SF_OPEN_READ_ONLY))
         if (!configFile.Open(configPath.c_str(), IO::SystemFile::OpenMode::SF_OPEN_READ_ONLY))
         {
         {
@@ -348,9 +477,13 @@ namespace AZ::SettingsRegistryMergeUtils
         ConfigParserSettings parserSettings;
         ConfigParserSettings parserSettings;
         parserSettings.m_commentPrefixFunc = [](AZStd::string_view line) -> AZStd::string_view
         parserSettings.m_commentPrefixFunc = [](AZStd::string_view line) -> AZStd::string_view
         {
         {
-            if (line.starts_with("--") || line.starts_with(';') || line.starts_with('#'))
+            constexpr AZStd::string_view commentPrefixes[]{ "--", ";","#" };
+            for (AZStd::string_view commentPrefix : commentPrefixes)
             {
             {
-                return {};
+                if (size_t commentOffset = line.find(commentPrefix); commentOffset != AZStd::string_view::npos)
+                {
+                    return line.substr(0, commentOffset);
+                }
             }
             }
             return line;
             return line;
         };
         };
@@ -365,71 +498,104 @@ namespace AZ::SettingsRegistryMergeUtils
         registry.Set(FilePathKey_BinaryFolder, path.LexicallyNormal().Native());
         registry.Set(FilePathKey_BinaryFolder, path.LexicallyNormal().Native());
 
 
         // Engine root folder - corresponds to the @engroot@ and @devroot@ aliases
         // Engine root folder - corresponds to the @engroot@ and @devroot@ aliases
-        AZ::IO::FixedMaxPath appRoot = GetAppRoot(&registry);
-        registry.Set(FilePathKey_EngineRootFolder, appRoot.LexicallyNormal().Native());
+        AZ::IO::FixedMaxPath engineRoot = FindEngineRoot(registry);
+        registry.Set(FilePathKey_EngineRootFolder, engineRoot.LexicallyNormal().Native());
 
 
         constexpr size_t bufferSize = 64;
         constexpr size_t bufferSize = 64;
-        auto buffer = AZStd::fixed_string<bufferSize>::format("%s/sys_game_folder", BootstrapSettingsRootKey);
+        auto buffer = AZStd::fixed_string<bufferSize>::format("%s/project_path", BootstrapSettingsRootKey);
 
 
-        AZStd::string_view projectPath(buffer);
+        AZ::SettingsRegistryInterface::FixedValueString projectPathKey(buffer);
         SettingsRegistryInterface::FixedValueString projectPathValue;
         SettingsRegistryInterface::FixedValueString projectPathValue;
-        if (registry.Get(projectPathValue, projectPath))
+        if (registry.Get(projectPathValue, projectPathKey))
         {
         {
             // Cache folder
             // Cache folder
             // Get the name of the asset platform assigned by the bootstrap. First check for platform version such as "windows_assets"
             // Get the name of the asset platform assigned by the bootstrap. First check for platform version such as "windows_assets"
-            // and if that's missing just get "asset".
+            // and if that's missing just get "assets".
             constexpr char platformName[] = AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER;
             constexpr char platformName[] = AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER;
 
 
             SettingsRegistryInterface::FixedValueString assetPlatform;
             SettingsRegistryInterface::FixedValueString assetPlatform;
             buffer = AZStd::fixed_string<bufferSize>::format("%s/%s_assets", BootstrapSettingsRootKey, platformName);
             buffer = AZStd::fixed_string<bufferSize>::format("%s/%s_assets", BootstrapSettingsRootKey, platformName);
-            AZStd::string_view assetPlatformatPath(buffer);
-            if (!registry.Get(assetPlatform, assetPlatformatPath))
+            AZStd::string_view assetPlatformKey(buffer);
+            if (!registry.Get(assetPlatform, assetPlatformKey))
             {
             {
                 buffer = AZStd::fixed_string<bufferSize>::format("%s/assets", BootstrapSettingsRootKey);
                 buffer = AZStd::fixed_string<bufferSize>::format("%s/assets", BootstrapSettingsRootKey);
-                assetPlatformatPath = AZStd::string_view(buffer);
-                if (!registry.Get(assetPlatform, assetPlatformatPath))
-                {
-                    return;
-                }
+                assetPlatformKey = AZStd::string_view(buffer);
+                registry.Get(assetPlatform, assetPlatformKey);
             }
             }
 
 
-            // Source game folder - corresponds to the @devassets@ alias
-            path = appRoot / projectPathValue;
+            // Project path - corresponds to the @devassets@ alias
+            // NOTE: Here we append to engineRoot, but if projectPathValue is absolute then engineRoot is discarded.
+            path = engineRoot / projectPathValue;
+
             AZ_Warning("SettingsRegistryMergeUtils", AZ::IO::SystemFile::Exists(path.c_str()),
             AZ_Warning("SettingsRegistryMergeUtils", AZ::IO::SystemFile::Exists(path.c_str()),
-                R"(Project Path "%s" does not exist. Is the "sys_game_folder" entry set to valid project folder?)"
-                , path.c_str());
-            registry.Set(FilePathKey_SourceGameFolder, path.LexicallyNormal().Native());
-
-            // Source game name - The filename of the project directory and the name of the project
-            registry.Set(FilePathKey_SourceGameName, path.Filename().Native());
-
-            // Cache root folder - corresponds to the @root@ alias
-#if AZ_TRAIT_USE_ASSET_CACHE_FOLDER
-            path = appRoot / "Cache" / projectPathValue / assetPlatform;
-#else
-            // Use the Engine Root/App Root as the Asset root directory in this case
-            path = appRoot;
-#endif
-            registry.Set(FilePathKey_CacheRootFolder, path.LexicallyNormal().Native());
-
-            // check for a default write storage path, fall back to the cache root if not
+                R"(Project path "%s" does not exist. Is the "%.*s" registry setting set to valid absolute path?)"
+                , path.c_str(), aznumeric_cast<int>(projectPathKey.size()), projectPathKey.data());
+
+            AZ::IO::FixedMaxPath normalizedProjectPath = path.LexicallyNormal();
+            registry.Set(FilePathKey_ProjectPath, normalizedProjectPath.Native());
+
+            // Add an alias to the project "user" directory
+            AZ::IO::FixedMaxPath projectUserPath = (normalizedProjectPath / "user").LexicallyNormal();
+            registry.Set(FilePathKey_ProjectUserPath, projectUserPath.Native());
+            // check for a default write storage path, fall back to the project's user/ directory if not
             AZStd::optional<AZ::IO::FixedMaxPathString> devWriteStorage = Utils::GetDevWriteStoragePath();
             AZStd::optional<AZ::IO::FixedMaxPathString> devWriteStorage = Utils::GetDevWriteStoragePath();
-            registry.Set(FilePathKey_DevWriteStorage,
-                devWriteStorage.has_value() ?
-                    devWriteStorage.value() :
-                    path.LexicallyNormal().Native());
-
-            // Cache game folder - corresponds to the @assets@ alias
-            AZStd::to_lower(projectPathValue.begin(), projectPathValue.end());
-            path /= projectPathValue;
-            registry.Set(FilePathKey_CacheGameFolder, path.LexicallyNormal().Native());
+            registry.Set(FilePathKey_DevWriteStorage, devWriteStorage.has_value()
+                ? devWriteStorage.value()
+                : projectUserPath.Native());
+
+            // Project name - if it was set via merging project.json use that value, otherwise use the project path's folder name.
+            auto projectNameKey =
+                AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey)
+                + "/project_name";
+
+            AZ::SettingsRegistryInterface::FixedValueString projectName;
+            if (!registry.Get(projectName, projectNameKey))
+            {
+                projectName = path.Filename().Native();
+                registry.Set(projectNameKey, projectName);
+            }
+
+            // Cache folders - sets up various paths in registry for the cache.
+            // Make sure the asset platform is set before setting these cache paths.
+            if (!assetPlatform.empty())
+            {
+                // Cache: project root - no corresponding fileIO alias, but this is where the asset database lives.
+                // A registry override is accepted using the "project_cache_path" key.
+                buffer = AZStd::fixed_string<bufferSize>::format("%s/project_cache_path", BootstrapSettingsRootKey);
+                AZStd::string_view projectCacheRootOverrideKey(buffer);
+                // Clear path to make sure that the `project_cache_path` value isn't concatenated to the project path
+                path.clear();
+                if (registry.Get(path.Native(), projectCacheRootOverrideKey))
+                {
+                    registry.Set(FilePathKey_CacheProjectRootFolder, path.LexicallyNormal().Native());
+                    path /= assetPlatform;
+                    registry.Set(FilePathKey_CacheRootFolder, path.LexicallyNormal().Native());
+                }
+                else
+                {
+                    // Cache: root - same as the @root@ alias, this is the starting path for cache files.
+                    path = normalizedProjectPath / "Cache";
+                    registry.Set(FilePathKey_CacheProjectRootFolder, path.LexicallyNormal().Native());
+                    path /= assetPlatform;
+                    registry.Set(FilePathKey_CacheRootFolder, path.LexicallyNormal().Native());
+                }
+            }
         }
         }
         else
         else
         {
         {
             AZ_TracePrintf("SettingsRegistryMergeUtils",
             AZ_TracePrintf("SettingsRegistryMergeUtils",
-                R"(Current Project game folder "%.*s" isn't set in the Settings Registry. Project-related filepaths will not be set)" "\n",
-                aznumeric_cast<int>(projectPath.size()), projectPath.data());
+                R"(Project path isn't set in the Settings Registry at "%.*s". Project-related filepaths will not be set)" "\n",
+                aznumeric_cast<int>(projectPathKey.size()), projectPathKey.data());
         }
         }
+
+#if !AZ_TRAIT_USE_ASSET_CACHE_FOLDER
+        // Setup the cache and user paths for Platforms where the Asset Cache Folder isn't used
+        path = engineRoot;
+        registry.Set(FilePathKey_CacheProjectRootFolder, path.LexicallyNormal().Native());
+        registry.Set(FilePathKey_CacheRootFolder, path.LexicallyNormal().Native());
+        registry.Set(FilePathKey_DevWriteStorage, path.LexicallyNormal().Native());
+        registry.Set(FilePathKey_ProjectUserPath, (path / "user").LexicallyNormal().Native());
+#endif // AZ_TRAIT_USE_ASSET_CACHE_FOLDER
     }
     }
 
 
     void MergeSettingsToRegistry_TargetBuildDependencyRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
     void MergeSettingsToRegistry_TargetBuildDependencyRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
@@ -535,7 +701,7 @@ namespace AZ::SettingsRegistryMergeUtils
         const SettingsRegistryInterface::Specializations& specializations, AZStd::vector<char>* scratchBuffer)
         const SettingsRegistryInterface::Specializations& specializations, AZStd::vector<char>* scratchBuffer)
     {
     {
         AZ::SettingsRegistryInterface::FixedValueString sourceGamePath;
         AZ::SettingsRegistryInterface::FixedValueString sourceGamePath;
-        if (registry.Get(sourceGamePath, FilePathKey_SourceGameFolder))
+        if (registry.Get(sourceGamePath, FilePathKey_ProjectPath))
         {
         {
             AZ::IO::FixedMaxPath mergePath{ sourceGamePath };
             AZ::IO::FixedMaxPath mergePath{ sourceGamePath };
             mergePath /= SettingsRegistryInterface::RegistryFolder;
             mergePath /= SettingsRegistryInterface::RegistryFolder;
@@ -543,26 +709,41 @@ namespace AZ::SettingsRegistryMergeUtils
         }
         }
     }
     }
 
 
-    void MergeSettingsToRegistry_DevRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
+    void MergeSettingsToRegistry_UserRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
         const SettingsRegistryInterface::Specializations& specializations, AZStd::vector<char>* scratchBuffer)
         const SettingsRegistryInterface::Specializations& specializations, AZStd::vector<char>* scratchBuffer)
     {
     {
         // Unlike other paths, the path can't be overwritten by the dev settings because that would create a circular dependency.
         // Unlike other paths, the path can't be overwritten by the dev settings because that would create a circular dependency.
-        auto mergePath = GetAppRoot(&registry);
-        mergePath /= SettingsRegistryInterface::DevUserRegistryFolder;
-        registry.MergeSettingsFolder(mergePath.Native(), specializations, platform, "", scratchBuffer);
+        AZ::IO::FixedMaxPath projectUserPath;
+        if (registry.Get(projectUserPath.Native(), FilePathKey_ProjectPath))
+        {
+            projectUserPath /= SettingsRegistryInterface::DevUserRegistryFolder;
+            registry.MergeSettingsFolder(projectUserPath.Native(), specializations, platform, "", scratchBuffer);
+        }
     }
     }
 
 
     void MergeSettingsToRegistry_CommandLine(SettingsRegistryInterface& registry, const AZ::CommandLine& commandLine, bool executeCommands)
     void MergeSettingsToRegistry_CommandLine(SettingsRegistryInterface& registry, const AZ::CommandLine& commandLine, bool executeCommands)
     {
     {
-        const size_t regsetSwitchValues = commandLine.GetNumSwitchValues("regset");
-        for (size_t regsetIndex = 0; regsetIndex < regsetSwitchValues; ++regsetIndex)
+        // Iterate over all the command line options in order to parse the --regset and --regremove
+        // arguments in the order they were supplied
+        for (const CommandLine::CommandArgument& commandArgument : commandLine)
         {
         {
-            AZStd::string_view regsetValue = commandLine.GetSwitchValue("regset", regsetIndex);
-            if (!registry.MergeCommandLineArgument(regsetValue, AZStd::string_view{}))
+            if (commandArgument.m_option == "regset")
             {
             {
-                AZ_Warning("SettingsRegistryMergeUtils", false, "Unable to parse argument for --regset with value of %.*s.",
-                    aznumeric_cast<int>(regsetValue.size()), regsetValue.data());
-                continue;
+                if (!registry.MergeCommandLineArgument(commandArgument.m_value, AZStd::string_view{}))
+                {
+                    AZ_Warning("SettingsRegistryMergeUtils", false, "Unable to parse argument for --regset with value of %s.",
+                        commandArgument.m_value.c_str());
+                    continue;
+                }
+            }
+            if (commandArgument.m_option == "regremove")
+            {
+                if (!registry.Remove(commandArgument.m_value))
+                {
+                    AZ_Warning("SettingsRegistryMergeUtils", false, "Unable to remove value at JSON Pointer %s for --regremove.",
+                        commandArgument.m_value.data());
+                    continue;
+                }
             }
             }
         }
         }
 
 
@@ -585,16 +766,8 @@ namespace AZ::SettingsRegistryMergeUtils
                 DumpSettingsRegistryToStream(registry, regdumpValue, outputStream, dumperSettings);
                 DumpSettingsRegistryToStream(registry, regdumpValue, outputStream, dumperSettings);
             }
             }
 
 
-            const size_t regdumpallSwitchValues = commandLine.GetNumSwitchValues("regdumpall");
-            if (regdumpallSwitchValues > 0)
+            if (commandLine.HasSwitch("regdumpall"))
             {
             {
-                AZStd::string_view regdumpallValue = commandLine.GetSwitchValue("regdumpall", 0);
-                if (regdumpallValue.empty())
-                {
-                    AZ_Warning("SettingsRegistryMergeUtils", false, "Unable to parse argument for --regdumpall with value of %.*s.",
-                        aznumeric_cast<int>(regdumpallValue.size()), regdumpallValue.data());
-                }
-
                 DumperSettings dumperSettings{ prettifyOutput };
                 DumperSettings dumperSettings{ prettifyOutput };
                 AZ::IO::StdoutStream outputStream;
                 AZ::IO::StdoutStream outputStream;
                 DumpSettingsRegistryToStream(registry, "", outputStream, dumperSettings);
                 DumpSettingsRegistryToStream(registry, "", outputStream, dumperSettings);
@@ -602,45 +775,54 @@ namespace AZ::SettingsRegistryMergeUtils
         }
         }
     }
     }
 
 
-    void MergeSettingsToRegistry_StoreCommandLine(SettingsRegistryInterface& registry, const AZ::CommandLine& commandLine)
+    void StoreCommandLineToRegistry(SettingsRegistryInterface& registry, const AZ::CommandLine& commandLine)
     {
     {
         // Clear out any existing CommandLine settings
         // Clear out any existing CommandLine settings
         registry.Remove(CommandLineRootKey);
         registry.Remove(CommandLineRootKey);
-        // Add the positional arguments into the Settings Registry
-        AZ::SettingsRegistryInterface::FixedValueString miscValueKey{ CommandLineMiscValuesRootKey };
-        size_t miscKeyRootSize = miscValueKey.size();
-        for (size_t miscIndex = 0; miscIndex < commandLine.GetNumMiscValues(); ++miscIndex)
-        {
-            // Push an array for each positional entry
-            miscValueKey += AZ::SettingsRegistryInterface::FixedValueString::format("/%zu", miscIndex);
-            registry.Set(miscValueKey, commandLine.GetMiscValue(miscIndex));
-            miscValueKey.resize(miscKeyRootSize);
+
+        AZ::SettingsRegistryInterface::FixedValueString commandLinePath{ CommandLineRootKey };
+        const size_t commandLineRootSize = commandLinePath.size();
+        size_t argumentIndex{};
+        for (const CommandLine::CommandArgument& commandArgument : commandLine)
+        {
+            commandLinePath += AZ::SettingsRegistryInterface::FixedValueString::format("/%zu", argumentIndex);
+            registry.Set(commandLinePath + "/Option", commandArgument.m_option);
+            registry.Set(commandLinePath + "/Value", commandArgument.m_value);
+            ++argumentIndex;
+            commandLinePath.resize(commandLineRootSize);
         }
         }
-        // Add the option arguments into the SettingsRegistry
-        for (const auto& [commandOption, value] : commandLine.GetSwitchList())
-        {
-            AZ::SettingsRegistryInterface::FixedValueString switchKey{ CommandLineSwitchRootKey };
-            switchKey += '/';
-            switchKey += commandOption;
-            size_t switchKeyRootSize = switchKey.size();
-            // Associate an empty array with the commandOption by default
-            rapidjson::Document commandSwitchDocument;
-            rapidjson::Pointer pointer(switchKey.c_str(), switchKey.length());
-            pointer.Set(commandSwitchDocument, rapidjson::Value(rapidjson::kArrayType));;
-            rapidjson::StringBuffer documentBuffer;
-            rapidjson::Writer documentWriter(documentBuffer);
-            commandSwitchDocument.Accept(documentWriter);
-            registry.MergeSettings(AZStd::string_view{ documentBuffer.GetString(), documentBuffer.GetSize() },
-                AZ::SettingsRegistryInterface::Format::JsonMergePatch);
-
-            for (size_t switchIndex = 0; switchIndex < value.size(); ++switchIndex)
-            {
-                // Push an array for each positional entry
-                switchKey += AZ::SettingsRegistryInterface::FixedValueString::format("/%zu", switchIndex);
-                registry.Set(switchKey, value[switchIndex]);
-                switchKey.resize(switchKeyRootSize);
+    }
+
+    bool GetCommandLineFromRegistry(SettingsRegistryInterface& registry, AZ::CommandLine& commandLine)
+    {
+        struct CommandLineVisitor
+            : AZ::SettingsRegistryInterface::Visitor
+        {
+            void Visit(AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type
+                , AZStd::string_view value) override
+            {
+                if (valueName == "Option" && !value.empty())
+                {
+                    m_arguments.push_back(AZStd::string::format("--%.*s", aznumeric_cast<int>(value.size()), value.data()));
+                }
+                else if (valueName == "Value" && !value.empty())
+                {
+                    m_arguments.push_back(value);
+                }
             }
             }
+
+            // The first parameter is skipped by the ComamndLine::Parse function so initialize
+            // the container with one empty element
+            AZ::CommandLine::ParamContainer m_arguments{ 1 };
+        };
+
+        CommandLineVisitor commandLineVisitor;
+        if (!registry.Visit(commandLineVisitor, AZ::SettingsRegistryMergeUtils::CommandLineRootKey))
+        {
+            return false;
         }
         }
+        commandLine.Parse(commandLineVisitor.m_arguments);
+        return true;
     }
     }
 
 
     bool DumpSettingsRegistryToStream(SettingsRegistryInterface& registry, AZStd::string_view key,
     bool DumpSettingsRegistryToStream(SettingsRegistryInterface& registry, AZStd::string_view key,
@@ -649,38 +831,21 @@ namespace AZ::SettingsRegistryMergeUtils
         struct SettingsExportVisitor
         struct SettingsExportVisitor
             : SettingsRegistryInterface::Visitor
             : SettingsRegistryInterface::Visitor
         {
         {
-            using SettingsWriter = AZStd::variant<
-                rapidjson::PrettyWriter<AZ::IO::RapidJSONStreamWriter>,
-                rapidjson::Writer<AZ::IO::RapidJSONStreamWriter>>;
-            SettingsWriter m_writer;
-            AZ::IO::RapidJSONStreamWriter m_rapidJsonStream;
-            DumperSettings m_dumperSettings;
-            AZStd::stack<bool> m_includeNameStack;
-            bool m_includeName{};
-            bool m_result{ true };
-
             SettingsExportVisitor(AZ::IO::GenericStream& stream, const DumperSettings& dumperSettings)
             SettingsExportVisitor(AZ::IO::GenericStream& stream, const DumperSettings& dumperSettings)
                 : m_rapidJsonStream{ &stream }
                 : m_rapidJsonStream{ &stream }
                 , m_dumperSettings{ dumperSettings }
                 , m_dumperSettings{ dumperSettings }
+                , m_writer{ m_stringBuffer }
             {
             {
-                if (m_dumperSettings.m_prettifyOutput)
-                {
-                    m_writer.emplace<rapidjson::PrettyWriter<AZ::IO::RapidJSONStreamWriter>>(m_rapidJsonStream);
-                }
-                else
-                {
-                    m_writer.emplace<rapidjson::Writer<AZ::IO::RapidJSONStreamWriter>>(m_rapidJsonStream);
-                }
             }
             }
-            void WriteName(AZStd::string_view name)
+            bool WriteName(AZStd::string_view name)
             {
             {
-                if (m_includeName)
+                // Write the Key if the include name stack the top element is true
+                if (!m_includeNameStack.empty() && m_includeNameStack.top())
                 {
                 {
-                    AZStd::visit([&name](auto&& writer)
-                    {
-                        writer.Key(name.data(), aznumeric_caster(name.size()));
-                    }, m_writer);
+                    return m_writer.Key(name.data(), aznumeric_caster(name.size()), false);
                 }
                 }
+
+                return true;
             }
             }
             AZ::SettingsRegistryInterface::VisitResponse Traverse(
             AZ::SettingsRegistryInterface::VisitResponse Traverse(
                 AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::VisitAction action,
                 AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::VisitAction action,
@@ -694,60 +859,43 @@ namespace AZ::SettingsRegistryMergeUtils
 
 
                 if (action == AZ::SettingsRegistryInterface::VisitAction::Begin)
                 if (action == AZ::SettingsRegistryInterface::VisitAction::Begin)
                 {
                 {
-                    AZ_Assert(type == AZ::SettingsRegistryInterface::Type::Object || type == AZ::SettingsRegistryInterface::Type::Array,
-                        "Unexpected type visited: %i.", type);
-                    WriteName(valueName);
+                    m_result = m_result && WriteName(valueName);
                     if (type == AZ::SettingsRegistryInterface::Type::Object)
                     if (type == AZ::SettingsRegistryInterface::Type::Object)
                     {
                     {
-                        auto StartObject = [](auto&& writer)
+                        m_result = m_result && m_writer.StartObject();
+                        if (m_result)
                         {
                         {
-                            return writer.StartObject();
-                        };
-                        m_result = m_result && AZStd::visit(StartObject, m_writer);
-                        m_includeNameStack.push(true);
-                        m_includeName = true;
+                            m_includeNameStack.push(true);
+                        }
                     }
                     }
                     else
                     else
                     {
                     {
-                        auto StartArray = [](auto&& writer)
+                        m_result = m_result && m_writer.StartArray();
+                        if (m_result)
                         {
                         {
-                            return writer.StartArray();
-                        };
-                        m_result = m_result && AZStd::visit(StartArray, m_writer);
-                        m_includeNameStack.push(false);
-                        m_includeName = false;
+                            m_includeNameStack.push(false);
+                        }
                     }
                     }
                 }
                 }
                 else if (action == AZ::SettingsRegistryInterface::VisitAction::End)
                 else if (action == AZ::SettingsRegistryInterface::VisitAction::End)
                 {
                 {
                     if (type == AZ::SettingsRegistryInterface::Type::Object)
                     if (type == AZ::SettingsRegistryInterface::Type::Object)
                     {
                     {
-                        auto EndObject = [](auto&& writer)
-                        {
-                            return writer.EndObject();
-                        };
-                        m_result = m_result && AZStd::visit(EndObject, m_writer);
+                        m_result = m_result && m_writer.EndObject();
                     }
                     }
                     else
                     else
                     {
                     {
-                        auto EndArray = [](auto&& writer)
-                        {
-                            return writer.EndArray();
-                        };
-                        m_result = m_result && AZStd::visit(EndArray, m_writer);
+                        m_result = m_result && m_writer.EndArray();
                     }
                     }
                     AZ_Assert(!m_includeNameStack.empty(), "Attempting to close a json array or object that wasn't started.");
                     AZ_Assert(!m_includeNameStack.empty(), "Attempting to close a json array or object that wasn't started.");
                     m_includeNameStack.pop();
                     m_includeNameStack.pop();
-                    m_includeName = !m_includeNameStack.empty() ? m_includeNameStack.top() : true;
                 }
                 }
-                else if (type == AZ::SettingsRegistryInterface::Type::Null)
+                else
                 {
                 {
-                    WriteName(valueName);
-                    auto WriteNull = [](auto&& writer)
+                    if (type == AZ::SettingsRegistryInterface::Type::Null)
                     {
                     {
-                        return writer.Null();
-                    };
-                    m_result = m_result && AZStd::visit(WriteNull, m_writer);
+                        m_result = m_result && WriteName(valueName) && m_writer.Null();
+                    }
                 }
                 }
 
 
                 return m_result ?
                 return m_result ?
@@ -757,42 +905,27 @@ namespace AZ::SettingsRegistryMergeUtils
 
 
             void Visit(AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, bool value)
             void Visit(AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, bool value)
             {
             {
-                WriteName(valueName);
-                auto WriteBool = [value](auto&& writer)
-                {
-                    return writer.Bool(value);
-                };
-                m_result = m_result && AZStd::visit(WriteBool, m_writer);
+                m_result = m_result && WriteName(valueName) && m_writer.Bool(value);
             }
             }
 
 
-            void Visit(AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZ::s64 value)
+            void Visit(AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZ::s64 value) override
             {
             {
-                WriteName(valueName);
-                auto WriteInt64 = [value](auto&& writer)
-                {
-                    return writer.Int64(value);
-                };
-                m_result = m_result && AZStd::visit(WriteInt64, m_writer);
+                m_result = m_result && WriteName(valueName) && m_writer.Int64(value);
+            }
+
+            void Visit(AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZ::u64 value) override
+            {
+                m_result = m_result && WriteName(valueName) && m_writer.Uint64(value);
             }
             }
 
 
             void Visit(AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, double value)
             void Visit(AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, double value)
             {
             {
-                WriteName(valueName);
-                auto WriteDouble = [value](auto&& writer)
-                {
-                    return writer.Double(value);
-                };
-                m_result = m_result && AZStd::visit(WriteDouble, m_writer);
+                m_result = m_result && WriteName(valueName) && m_writer.Double(value);
             }
             }
 
 
             void Visit(AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value)
             void Visit(AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value)
             {
             {
-                WriteName(valueName);
-                auto WriteString = [&value](auto&& writer)
-                {
-                    return writer.String(value.data(), aznumeric_caster(value.size()));
-                };
-                m_result = m_result && AZStd::visit(WriteString, m_writer);
+                m_result = m_result && WriteName(valueName) && m_writer.String(value.data(), aznumeric_caster(value.size()));
             }
             }
 
 
             bool Finalize()
             bool Finalize()
@@ -802,8 +935,46 @@ namespace AZ::SettingsRegistryMergeUtils
                     AZ_Assert(false, "m_includeNameStack is expected to be empty. This means that there was an object or array what wasn't closed.");
                     AZ_Assert(false, "m_includeNameStack is expected to be empty. This means that there was an object or array what wasn't closed.");
                     return false;
                     return false;
                 }
                 }
-                return m_result;
+
+                // Root the JSON document underneath the JSON pointer prefix if non-empty
+                // Parse non-anchored JSON data into a document and then re-root
+                // that document under the prefix value
+                rapidjson::Document document;
+                document.Parse(m_stringBuffer.GetString(), m_stringBuffer.GetSize());
+
+                rapidjson::Document rootDocument;
+                AZStd::string_view jsonPrefix{ m_dumperSettings.m_jsonPointerPrefix };
+                if (!jsonPrefix.empty())
+                {
+                    rapidjson::Pointer rootPointer(jsonPrefix.data(), jsonPrefix.size());
+                    rapidjson::SetValueByPointer(rootDocument, rootPointer, document);
+                }
+                else
+                {
+                    rootDocument = AZStd::move(document);
+                }
+
+                if (m_dumperSettings.m_prettifyOutput)
+                {
+                    rapidjson::PrettyWriter settingsWriter(m_rapidJsonStream);
+                    rootDocument.Accept(settingsWriter);
+                }
+                else
+                {
+                    rapidjson::Writer settingsWriter(m_rapidJsonStream);
+                    rootDocument.Accept(settingsWriter);
+                }
+
+                return true;
             }
             }
+
+            rapidjson::StringBuffer m_stringBuffer;
+            rapidjson::Writer<rapidjson::StringBuffer> m_writer;
+
+            AZ::IO::RapidJSONStreamWriter m_rapidJsonStream;
+            DumperSettings m_dumperSettings;
+            AZStd::stack<bool> m_includeNameStack;
+            bool m_result{ true };
         };
         };
 
 
         SettingsExportVisitor visitor(stream, dumperSettings);
         SettingsExportVisitor visitor(stream, dumperSettings);

+ 59 - 24
Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h

@@ -36,27 +36,45 @@ namespace AZ::SettingsRegistryMergeUtils
     inline static constexpr char FilePathsRootKey[] = "/Amazon/AzCore/Runtime/FilePaths";
     inline static constexpr char FilePathsRootKey[] = "/Amazon/AzCore/Runtime/FilePaths";
     inline static constexpr char FilePathKey_BinaryFolder[] = "/Amazon/AzCore/Runtime/FilePaths/BinaryFolder";
     inline static constexpr char FilePathKey_BinaryFolder[] = "/Amazon/AzCore/Runtime/FilePaths/BinaryFolder";
     inline static constexpr char FilePathKey_EngineRootFolder[] = "/Amazon/AzCore/Runtime/FilePaths/EngineRootFolder";
     inline static constexpr char FilePathKey_EngineRootFolder[] = "/Amazon/AzCore/Runtime/FilePaths/EngineRootFolder";
+
+    //! Stores the absolute path to root of a project's cache.  No asset platform in this path, this is where the asset database file lives.
+    //! i.e. <ProjectPath>/Cache
+    inline static constexpr char FilePathKey_CacheProjectRootFolder[] = "/Amazon/AzCore/Runtime/FilePaths/CacheProjectRootFolder";
+
+    //! Stores the absolute path to the cache root for an asset platform.  This is the @root@ alias.
+    //! i.e. <ProjectPath>/Cache/<assetplatform>
     inline static constexpr char FilePathKey_CacheRootFolder[] = "/Amazon/AzCore/Runtime/FilePaths/CacheRootFolder";
     inline static constexpr char FilePathKey_CacheRootFolder[] = "/Amazon/AzCore/Runtime/FilePaths/CacheRootFolder";
-    inline static constexpr char FilePathKey_CacheGameFolder[] = "/Amazon/AzCore/Runtime/FilePaths/CacheGameFolder";
-    inline static constexpr char FilePathKey_SourceGameFolder[] = "/Amazon/AzCore/Runtime/FilePaths/SourceGameFolder";
-    //! Stores the filename of the Game Project Directory which is equivalent to the project name
-    inline static constexpr char FilePathKey_SourceGameName[] = "/Amazon/AzCore/Runtime/FilePaths/SourceGameName";
+
+    //! Stores the absolute path of the Game Project Directory
+    inline static constexpr char FilePathKey_ProjectPath[] = "/Amazon/AzCore/Runtime/FilePaths/SourceProjectPath";
+
+    //! Store the absolute path to the Projects "user" directory, which is a transient directory where per user
+    //! project settings can be stored
+    inline static constexpr char FilePathKey_ProjectUserPath[] = "/Amazon/AzCore/Runtime/FilePaths/SourceProjectUserPath";
+
     //! Development write storage path may be considered temporary or cache storage on some platforms
     //! Development write storage path may be considered temporary or cache storage on some platforms
     inline static constexpr char FilePathKey_DevWriteStorage[] = "/Amazon/AzCore/Runtime/FilePaths/DevWriteStorage";
     inline static constexpr char FilePathKey_DevWriteStorage[] = "/Amazon/AzCore/Runtime/FilePaths/DevWriteStorage";
 
 
-    //! Root key for where command line are stored at witin the settings registry
+    //! Root key for where command line are stored at within the settings registry
     inline static constexpr char CommandLineRootKey[] = "/Amazon/AzCore/Runtime/CommandLine";
     inline static constexpr char CommandLineRootKey[] = "/Amazon/AzCore/Runtime/CommandLine";
-    //! Root key for command line switches(arguments that start with "-" or "--")
-    inline static constexpr char CommandLineSwitchRootKey[] = "/Amazon/AzCore/Runtime/CommandLine/Switches";
-    //! Root key for command line positional arguments
-    inline static constexpr char CommandLineMiscValuesRootKey[] = "/Amazon/AzCore/Runtime/CommandLine/MiscValues";
-
-    //! Examines the Settings Registry for a "/Amazon/CommandLine/Switches/app-root" key
-    //! to use as an override for the Application Root.
-    //! If that key is not found, it then checks the AZ::Utils::GetDefaultAppRootPath and returns that if it is value
+
+    //! Root key where raw project settings (project.json) file is merged to settings registry
+    inline static constexpr char ProjectSettingsRootKey[] = "/Amazon/Project/Settings";
+
+    //! Root key where raw engine manifest (o3de_manifest.json) file is merged to settings registry
+    inline static constexpr char EngineManifestRootKey[] = "/Amazon/Engine/Manifest";
+
+    //! Root key where raw engine settings (engine.json) file is merged to settings registry
+    inline static constexpr char EngineSettingsRootKey[] = "/Amazon/Engine/Settings";
+
+    //! Examines the Settings Registry for a "${BootstrapSettingsRootKey}/engine_path" key
+    //! to use as an override for the Engine Root.
     //! Otherwise a directory walk upwards from the executable directory is performed
     //! Otherwise a directory walk upwards from the executable directory is performed
-    //! to find the boostrap.cfg file which will be used as the app root
-    AZ::IO::FixedMaxPath GetAppRoot(SettingsRegistryInterface* settingsRegistry = nullptr);
+    //! to find the engine.json file which will be used as the engine root
+    //! If it's still not found, attempt to find the project (by similar means) then reconcile the
+    //! engine root by inspecting project.json and the engine manifest file.
+    AZ::IO::FixedMaxPath FindEngineRoot(SettingsRegistryInterface& settingsRegistry);
+    AZ::IO::FixedMaxPath FindProjectRoot(SettingsRegistryInterface& settingsRegistry);
 
 
     //! Query the specializations that will be used when loading the Settings Registry.
     //! Query the specializations that will be used when loading the Settings Registry.
     //! The SpecializationsRootKey is visited to retrieve any specializations stored within that section of that registry
     //! The SpecializationsRootKey is visited to retrieve any specializations stored within that section of that registry
@@ -151,16 +169,18 @@ namespace AZ::SettingsRegistryMergeUtils
     void MergeSettingsToRegistry_ProjectRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
     void MergeSettingsToRegistry_ProjectRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
         const SettingsRegistryInterface::Specializations& specializations, AZStd::vector<char>* scratchBuffer = nullptr);
         const SettingsRegistryInterface::Specializations& specializations, AZStd::vector<char>* scratchBuffer = nullptr);
 
 
-    //! Adds the development settings added by individual users to the Settings Registry.
+    //! Adds the development settings added by individual users of the project to the Settings Registry.
     //! Note that this function is only called in development builds and is compiled out in release builds.
     //! Note that this function is only called in development builds and is compiled out in release builds.
-    void MergeSettingsToRegistry_DevRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
+    void MergeSettingsToRegistry_UserRegistry(SettingsRegistryInterface& registry, const AZStd::string_view platform,
         const SettingsRegistryInterface::Specializations& specializations, AZStd::vector<char>* scratchBuffer = nullptr);
         const SettingsRegistryInterface::Specializations& specializations, AZStd::vector<char>* scratchBuffer = nullptr);
 
 
     //! Adds the settings set through the command line to the Settings Registry. This will also execute any Settings
     //! Adds the settings set through the command line to the Settings Registry. This will also execute any Settings
-    //! Registry related arguments. Note that --set will be run first and all other commands are run afterwards and only
-    //! if executeCommands is true. The following options are supported:
+    //! Registry related arguments. Note that --regset and -regremove will run in the order in which they are parsed
     //! --regset <arg> Sets a value in the registry. See MergeCommandLineArgument for options for <arg>
     //! --regset <arg> Sets a value in the registry. See MergeCommandLineArgument for options for <arg>
     //!     example: --regset "/My/String/Value=String value set"
     //!     example: --regset "/My/String/Value=String value set"
+    //! --regremove <arg> Removes a value in the registry
+    //!    example: --regremove "/My/String/Value"
+    //! only when executeCommands is true are the following options supported:
     //! --regdump <path> Dumps the content of the key at path and all it's content/children to output.
     //! --regdump <path> Dumps the content of the key at path and all it's content/children to output.
     //!     example: --regdump /My/Array/With/Objects
     //!     example: --regdump /My/Array/With/Objects
     //! --regdumpall Dumps the entire settings registry to output.
     //! --regdumpall Dumps the entire settings registry to output.
@@ -169,7 +189,11 @@ namespace AZ::SettingsRegistryMergeUtils
 
 
     //! Stores the command line settings into the Setting Registry
     //! Stores the command line settings into the Setting Registry
     //! The arguments can be used later anywhere the command line is needed
     //! The arguments can be used later anywhere the command line is needed
-    void MergeSettingsToRegistry_StoreCommandLine(SettingsRegistryInterface& registry, const AZ::CommandLine& commandLine);
+    void StoreCommandLineToRegistry(SettingsRegistryInterface& registry, const AZ::CommandLine& commandLine);
+
+    //! Query the command line settings from the Setting Registry and stores them
+    //! into the AZ::CommandLine instance
+    bool GetCommandLineFromRegistry(SettingsRegistryInterface& registry, AZ::CommandLine& commandLine);
 
 
     //! Structure for configuring how values should be dumped from the Settings Registry
     //! Structure for configuring how values should be dumped from the Settings Registry
     struct DumperSettings
     struct DumperSettings
@@ -179,14 +203,25 @@ namespace AZ::SettingsRegistryMergeUtils
         //! Include filter which is used to indicate which paths of the Settings Registry
         //! Include filter which is used to indicate which paths of the Settings Registry
         //! should be traversed.
         //! should be traversed.
         //! If the include filter is empty then all paths underneath the JSON pointer path are included
         //! If the include filter is empty then all paths underneath the JSON pointer path are included
-        //! otherwise the include filter invoked and if it returns true does it proceed with traversal continues down the path
+        //! otherwise the include filter invoked and if it returns true does it proceed with traversal down the path
+        //! The supplied JSON pointer will be a complete path from the root of the registry
         AZStd::function<bool(AZStd::string_view path)> m_includeFilter;
         AZStd::function<bool(AZStd::string_view path)> m_includeFilter;
+        //! JSON pointer prefix to dump all settings underneath
+        //! For example if the prefix is "/Amazon/Settings", then the dumped settings will be placed underneath
+        //! an object at that path
+        //! """
+        //! {
+        //!   "Amazon":{
+        //!     "Settings":{ <Dumped values> }
+        //!   }
+        //! }
+        AZStd::string_view m_jsonPointerPrefix;
     };
     };
 
 
     //! Dumps supplied settings registry from the path specified by key if it exist the the AZ::IO::GenericStream
     //! Dumps supplied settings registry from the path specified by key if it exist the the AZ::IO::GenericStream
-    //! key is a JSON pointer path to dumping settings recursively from
-    //! stream is an AZ::IO::GenericStream that supports writing
-    //! dumperSettings are used to determine how to format the dumped output
+    //! @param key is a JSON pointer to recursively dump settings from
+    //! @param stream is an AZ::IO::GenericStream that supports writing
+    //! @param dumperSettings are used to determine how to format the dumped output
     bool DumpSettingsRegistryToStream(SettingsRegistryInterface& registry, AZStd::string_view key,
     bool DumpSettingsRegistryToStream(SettingsRegistryInterface& registry, AZStd::string_view key,
         AZ::IO::GenericStream& stream, const DumperSettings& dumperSettings);
         AZ::IO::GenericStream& stream, const DumperSettings& dumperSettings);
 
 

+ 52 - 28
Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp

@@ -418,36 +418,37 @@ namespace AZ::StringFunc::Internal
         return Strip(inout, { &stripCharacter, 1 }, bCaseSensitive, bStripBeginning, bStripEnding);
         return Strip(inout, { &stripCharacter, 1 }, bCaseSensitive, bStripBeginning, bStripEnding);
     }
     }
 
 
-    AZStd::string_view LStrip(AZStd::string_view in, AZStd::string_view stripCharacters)
+}
+
+namespace AZ
+{
+    namespace StringFunc
     {
     {
-        if (size_t pos = in.find_first_not_of(stripCharacters); pos != AZStd::string_view::npos)
+        AZStd::string_view LStrip(AZStd::string_view in, AZStd::string_view stripCharacters)
         {
         {
-            return in.substr(pos);
-        }
+            if (size_t pos = in.find_first_not_of(stripCharacters); pos != AZStd::string_view::npos)
+            {
+                return in.substr(pos);
+            }
 
 
-        return {};
-    };
+            return {};
+        };
 
 
-    AZStd::string_view RStrip(AZStd::string_view in, AZStd::string_view stripCharacters)
-    {
-        if (size_t pos = in.find_last_not_of(stripCharacters); pos != AZStd::string_view::npos)
+        AZStd::string_view RStrip(AZStd::string_view in, AZStd::string_view stripCharacters)
         {
         {
-            return in.substr(0, pos < in.size() ? pos + 1 : pos);
-        }
+            if (size_t pos = in.find_last_not_of(stripCharacters); pos != AZStd::string_view::npos)
+            {
+                return in.substr(0, pos < in.size() ? pos + 1 : pos);
+            }
 
 
-        return {};
-    };
+            return {};
+        };
 
 
-    AZStd::string_view StripEnds(AZStd::string_view in, AZStd::string_view stripCharacters)
-    {
-        return LStrip(RStrip(in, stripCharacters), stripCharacters);
-    };
-}
+        AZStd::string_view StripEnds(AZStd::string_view in, AZStd::string_view stripCharacters)
+        {
+            return LStrip(RStrip(in, stripCharacters), stripCharacters);
+        };
 
 
-namespace AZ
-{
-    namespace StringFunc
-    {
         bool Equal(const char* inA, const char* inB, bool bCaseSensitive /*= false*/, size_t n /*= 0*/)
         bool Equal(const char* inA, const char* inB, bool bCaseSensitive /*= false*/, size_t n /*= 0*/)
         {
         {
             if (!inA || !inB)
             if (!inA || !inB)
@@ -483,6 +484,14 @@ namespace AZ
                 }
                 }
             }
             }
         }
         }
+        bool Equal(AZStd::string_view inA, AZStd::string_view inB, bool bCaseSensitive)
+        {
+            const size_t maxCharsToCompare = inA.size();
+
+            return inA.size() == inB.size() && (bCaseSensitive
+                ? strncmp(inA.data(), inB.data(), maxCharsToCompare) == 0
+                : azstrnicmp(inA.data(), inB.data(), maxCharsToCompare) == 0);
+        }
 
 
         bool StartsWith(AZStd::string_view sourceValue, AZStd::string_view prefixValue, bool bCaseSensitive)
         bool StartsWith(AZStd::string_view sourceValue, AZStd::string_view prefixValue, bool bCaseSensitive)
         {
         {
@@ -496,9 +505,18 @@ namespace AZ
                 && Equal(sourceValue.substr(sourceValue.size() - suffixValue.size(), AZStd::string_view::npos).data(), suffixValue.data(), bCaseSensitive, suffixValue.size());
                 && Equal(sourceValue.substr(sourceValue.size() - suffixValue.size(), AZStd::string_view::npos).data(), suffixValue.data(), bCaseSensitive, suffixValue.size());
         }
         }
 
 
-        size_t Find(const char* in, char c, size_t pos /*= 0*/, bool bReverse /*= false*/, bool bCaseSensitive /*= false*/)
+        bool Contains(AZStd::string_view in, char ch, bool bCaseSensitive)
         {
         {
-            if (!in)
+            return Find(in, ch, 0, false, bCaseSensitive) != AZStd::string_view::npos;
+        }
+        bool Contains(AZStd::string_view in, AZStd::string_view sv, bool bCaseSensitive)
+        {
+            return Find(in, sv, 0, false, bCaseSensitive) != AZStd::string_view::npos;
+        }
+
+        size_t Find(AZStd::string_view in, char c, size_t pos /*= 0*/, bool bReverse /*= false*/, bool bCaseSensitive /*= false*/)
+        {
+            if (in.empty())
             {
             {
                 return AZStd::string::npos;
                 return AZStd::string::npos;
             }
             }
@@ -508,7 +526,7 @@ namespace AZ
                 pos = 0;
                 pos = 0;
             }
             }
 
 
-            size_t inLen = strlen(in);
+            size_t inLen = in.size();
             if (inLen < pos)
             if (inLen < pos)
             {
             {
                 return AZStd::string::npos;
                 return AZStd::string::npos;
@@ -557,7 +575,13 @@ namespace AZ
 
 
         size_t Find(AZStd::string_view in, AZStd::string_view s, size_t offset /*= 0*/, bool bReverse /*= false*/, bool bCaseSensitive /*= false*/)
         size_t Find(AZStd::string_view in, AZStd::string_view s, size_t offset /*= 0*/, bool bReverse /*= false*/, bool bCaseSensitive /*= false*/)
         {
         {
-            if (in.empty() || s.empty())
+            // Formally an empty string matches at the offset if it is <= to the size of the input string
+            if (s.empty() && offset <= in.size())
+            {
+                return offset;
+            }
+
+            if (in.empty())
             {
             {
                 return AZStd::string::npos;
                 return AZStd::string::npos;
             }
             }
@@ -773,7 +797,7 @@ namespace AZ
                 bool bIsSpaces = false;
                 bool bIsSpaces = false;
                 if (!bIsEmpty)
                 if (!bIsEmpty)
                 {
                 {
-                    AZStd::string_view strippedNextToken = Internal::StripEnds(*nextToken, " ");
+                    AZStd::string_view strippedNextToken = StripEnds(*nextToken, " ");
                     bIsSpaces = strippedNextToken.empty();
                     bIsSpaces = strippedNextToken.empty();
                 }
                 }
 
 
@@ -805,7 +829,7 @@ namespace AZ
                 bool bIsSpaces = false;
                 bool bIsSpaces = false;
                 if (!bIsEmpty)
                 if (!bIsEmpty)
                 {
                 {
-                    AZStd::string_view strippedNextToken = Internal::StripEnds(*nextToken, " ");
+                    AZStd::string_view strippedNextToken = StripEnds(*nextToken, " ");
                     bIsSpaces = strippedNextToken.empty();
                     bIsSpaces = strippedNextToken.empty();
                 }
                 }
 
 

+ 47 - 4
Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h

@@ -12,6 +12,7 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <AzCore/IO/Path/Path_fwd.h>
 #include <AzCore/std/function/function_fwd.h>
 #include <AzCore/std/function/function_fwd.h>
 #include <AzCore/std/string/fixed_string.h>
 #include <AzCore/std/string/fixed_string.h>
 #include <AzCore/std/string/string.h>
 #include <AzCore/std/string/string.h>
@@ -107,6 +108,22 @@ namespace AZ
         StringFunc::Equal("Hello World", "Hello", true, 3) = true
         StringFunc::Equal("Hello World", "Hello", true, 3) = true
         */
         */
         bool Equal(const char* inA, const char* inB, bool bCaseSensitive = false, size_t n = 0);
         bool Equal(const char* inA, const char* inB, bool bCaseSensitive = false, size_t n = 0);
+        bool Equal(AZStd::string_view inA, AZStd::string_view inB, bool bCaseSensitive = false);
+
+        //! Contains
+        /*! Checks if the supplied character or string is contained within the @in parameter
+        *
+        Example: Case Insensitive contains finds character
+        StringFunc::Contains("Hello", 'L') == true
+        Example: Case Sensitive contains finds character
+        StringFunc::Contains("Hello", 'l', true) = true
+        Example: Case Insensitive contains does not find string
+        StringFunc::Contains("Well Hello", "Mello") == false
+        Example: Case Sensitive contains does not find character
+        StringFunc::Contains("HeLlo", 'h', true) == false
+        */
+        bool Contains(AZStd::string_view in, char ch, bool bCaseSensitive = false);
+        bool Contains(AZStd::string_view in, AZStd::string_view sv, bool bCaseSensitive = false);
 
 
         //! Find
         //! Find
         /*! Find for non AZStd::strings. Ease of use to find the first or last occurrence of a character or substring in a c-string with case sensitivity.
         /*! Find for non AZStd::strings. Ease of use to find the first or last occurrence of a character or substring in a c-string with case sensitivity.
@@ -119,7 +136,7 @@ namespace AZ
         Example: Case Sensitive find first occurrence of substring "Hello" a in a c-string
         Example: Case Sensitive find first occurrence of substring "Hello" a in a c-string
         StringFunc::Find("Well Hello", "Hello", false, true) == 5
         StringFunc::Find("Well Hello", "Hello", false, true) == 5
         */
         */
-        size_t Find(const char* in, char c, size_t pos = 0, bool bReverse = false, bool bCaseSensitive = false);
+        size_t Find(AZStd::string_view in, char c, size_t pos = 0, bool bReverse = false, bool bCaseSensitive = false);
         size_t Find(AZStd::string_view in, AZStd::string_view str, size_t pos = 0, bool bReverse = false, bool bCaseSensitive = false);
         size_t Find(AZStd::string_view in, AZStd::string_view str, size_t pos = 0, bool bReverse = false, bool bCaseSensitive = false);
 
 
         //! First and Last Character
         //! First and Last Character
@@ -196,6 +213,33 @@ namespace AZ
         */
         */
         AZStd::string& TrimWhiteSpace(AZStd::string& value, bool leading, bool trailing);
         AZStd::string& TrimWhiteSpace(AZStd::string& value, bool leading, bool trailing);
 
 
+        //! LStrip
+        /*! Strips leading characters in the stripCharacters set
+        * Example
+        * Example: Case Insensitive Strip leading 'a' characters
+        * StringFunc::LStrip(s = "Abracadabra", 'a'); s == "bracadabra"
+        * Example: Case Sensitive Strip leading 'a' characters
+        * StringFunc::LStrip(s = "Abracadabra", 'a'); s == "Abracadabra"
+        */
+        //! RStrip
+        /*! Strips trailing characters in the stripCharacters set
+        * Example
+        * Example: Case Insensitive Strip trailing 'a' characters
+        * StringFunc::RStrip(s = "AbracadabrA", 'a'); s == "Abracadabr"
+        * Example: Case Sensitive Strip trailing 'a' characters
+        * StringFunc::RStrip(s = "AbracadabrA", 'a'); s == "AbracadabrA"
+        */
+        //! StripEnds
+        /*! Strips leading and trailing characters in the stripCharacters set
+        Example: Case Insensitive Strip all 'a' characters
+        StringFunc::StripEnds(s = "Abracadabra", 'a'); s == "bracadabr"
+        Example: Case Sensitive Strip all 'a' characters
+        StringFunc::StripEnds(s = "Abracadabra", 'a'); s == "Abracadabr"
+        */
+        AZStd::string_view LStrip(AZStd::string_view in, AZStd::string_view stripCharacters = " ");
+        AZStd::string_view RStrip(AZStd::string_view in, AZStd::string_view stripCharacters = " ");
+        AZStd::string_view StripEnds(AZStd::string_view in, AZStd::string_view stripCharacters = " ");
+
         //! Strip
         //! Strip
         /*! Strip away the leading, trailing or all character(s) or substring(s) in a AZStd::string with
         /*! Strip away the leading, trailing or all character(s) or substring(s) in a AZStd::string with
         *! case sensitivity.
         *! case sensitivity.
@@ -669,8 +713,7 @@ namespace AZ
          */
          */
         namespace Path
         namespace Path
         {
         {
-            inline constexpr size_t MaxPathLength = 1024;
-            using FixedString = AZStd::fixed_string<MaxPathLength>;
+            using FixedString = AZ::IO::FixedMaxPathString;
             //! Normalize
             //! Normalize
             /*! Normalizes a path and returns returns StringFunc::Path::IsValid()
             /*! Normalizes a path and returns returns StringFunc::Path::IsValid()
              *! strips all AZ_FILESYSTEM_INVALID_CHARACTERS
              *! strips all AZ_FILESYSTEM_INVALID_CHARACTERS
@@ -791,7 +834,7 @@ namespace AZ
 
 
             //! StripFullName
             //! StripFullName
             /*! gets rid of the full file name if it has one, returns if it removed one or not
             /*! gets rid of the full file name if it has one, returns if it removed one or not
-            *! EX: StringFunc::Path::StripFullName(a="C:\\p4\\game\\info\\some.file") == true; a=="C:\\p4\\game\\info\\"
+            *! EX: StringFunc::Path::StripFullName(a="C:\\p4\\game\\info\\some.file") == true; a=="C:\\p4\\game\\info"
             */
             */
             void StripFullName(AZStd::string& out);
             void StripFullName(AZStd::string& out);
 
 

+ 1 - 0
Code/Framework/AzCore/AzCore/UnitTest/MockComponentApplication.h

@@ -39,6 +39,7 @@ namespace UnitTest
         MOCK_METHOD0(GetJsonRegistrationContext, AZ::JsonRegistrationContext* ());
         MOCK_METHOD0(GetJsonRegistrationContext, AZ::JsonRegistrationContext* ());
         MOCK_METHOD0(GetBehaviorContext, AZ::BehaviorContext* ());
         MOCK_METHOD0(GetBehaviorContext, AZ::BehaviorContext* ());
         MOCK_CONST_METHOD0(GetAppRoot, const char* ());
         MOCK_CONST_METHOD0(GetAppRoot, const char* ());
+        MOCK_CONST_METHOD0(GetEngineRoot, const char* ());
         MOCK_CONST_METHOD0(GetExecutableFolder, const char* ());
         MOCK_CONST_METHOD0(GetExecutableFolder, const char* ());
         MOCK_METHOD0(GetDrillerManager, AZ::Debug::DrillerManager* ());
         MOCK_METHOD0(GetDrillerManager, AZ::Debug::DrillerManager* ());
         MOCK_CONST_METHOD1(QueryApplicationType, void(AZ::ApplicationTypeQuery&));
         MOCK_CONST_METHOD1(QueryApplicationType, void(AZ::ApplicationTypeQuery&));

+ 1 - 0
Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockFileIOBase.h

@@ -60,6 +60,7 @@ namespace AZ
             MOCK_CONST_METHOD2(ConvertToAlias, bool(AZ::IO::FixedMaxPath& aliasPath, const AZ::IO::PathView& path));
             MOCK_CONST_METHOD2(ConvertToAlias, bool(AZ::IO::FixedMaxPath& aliasPath, const AZ::IO::PathView& path));
             MOCK_CONST_METHOD3(ResolvePath, bool(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize));
             MOCK_CONST_METHOD3(ResolvePath, bool(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize));
             MOCK_CONST_METHOD2(ResolvePath, bool(AZ::IO::FixedMaxPath& resolvedPath, const AZ::IO::PathView& path));
             MOCK_CONST_METHOD2(ResolvePath, bool(AZ::IO::FixedMaxPath& resolvedPath, const AZ::IO::PathView& path));
+            MOCK_CONST_METHOD2(ReplaceAlias, bool(AZ::IO::FixedMaxPath& replacedAliasPath, const AZ::IO::PathView& path));
             MOCK_CONST_METHOD3(GetFilename, bool(HandleType fileHandle, char* filename, AZ::u64 filenameSize));
             MOCK_CONST_METHOD3(GetFilename, bool(HandleType fileHandle, char* filename, AZ::u64 filenameSize));
             using FileIOBase::ConvertToAlias;
             using FileIOBase::ConvertToAlias;
             using FileIOBase::ResolvePath;
             using FileIOBase::ResolvePath;

+ 43 - 0
Code/Framework/AzCore/AzCore/Utils/Utils.cpp

@@ -16,6 +16,8 @@
 #include <AzCore/IO/GenericStreams.h>
 #include <AzCore/IO/GenericStreams.h>
 #include <AzCore/IO/SystemFile.h>
 #include <AzCore/IO/SystemFile.h>
 #include <AzCore/IO/Path/Path.h>
 #include <AzCore/IO/Path/Path.h>
+#include <AzCore/Settings/SettingsRegistry.h>
+#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
 #include <AzCore/StringFunc/StringFunc.h>
 #include <AzCore/StringFunc/StringFunc.h>
 
 
 namespace AZ::Utils
 namespace AZ::Utils
@@ -40,6 +42,47 @@ namespace AZ::Utils
         return result.m_pathStored;
         return result.m_pathStored;
     }
     }
 
 
+    AZ::IO::FixedMaxPathString GetEnginePath()
+    {
+        if (auto registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            AZ::SettingsRegistryInterface::FixedValueString settingsValue;
+            if (registry->Get(settingsValue, AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder))
+            {
+                return AZ::IO::FixedMaxPathString{settingsValue};
+            }
+        }
+        return {};
+    }
+
+    AZ::IO::FixedMaxPathString GetProjectPath()
+    {
+        if (auto registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            AZ::SettingsRegistryInterface::FixedValueString settingsValue;
+            if (registry->Get(settingsValue, AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath))
+            {
+                return AZ::IO::FixedMaxPathString{settingsValue};
+            }
+        }
+        return {};
+    }
+
+    AZ::SettingsRegistryInterface::FixedValueString GetProjectName()
+    {
+        if (auto registry = AZ::SettingsRegistry::Get(); registry != nullptr)
+        {
+            AZ::SettingsRegistryInterface::FixedValueString projectNameKey{ AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey };
+            projectNameKey += "/project_name";
+            AZ::SettingsRegistryInterface::FixedValueString settingsValue;
+            if (registry->Get(settingsValue, projectNameKey))
+            {
+                return settingsValue;
+            }
+        }
+        return {};
+    }
+
     AZ::Outcome<void, AZStd::string> WriteFile(AZStd::string_view content, AZStd::string_view filePath)
     AZ::Outcome<void, AZStd::string> WriteFile(AZStd::string_view content, AZStd::string_view filePath)
     {
     {
         AZ::IO::FixedMaxPath filePathFixed = filePath; // Because FileIOStream requires a null-terminated string
         AZ::IO::FixedMaxPath filePathFixed = filePath; // Because FileIOStream requires a null-terminated string

+ 16 - 5
Code/Framework/AzCore/AzCore/Utils/Utils.h

@@ -16,6 +16,8 @@
 #include <AzCore/base.h>
 #include <AzCore/base.h>
 #include <AzCore/IO/Path/Path.h>
 #include <AzCore/IO/Path/Path.h>
 #include <AzCore/Outcome/Outcome.h>
 #include <AzCore/Outcome/Outcome.h>
+#include <AzCore/IO/Path/Path.h>
+#include <AzCore/Settings/SettingsRegistry.h>
 #include <AzCore/std/optional.h>
 #include <AzCore/std/optional.h>
 #include <AzCore/std/string/string.h>
 #include <AzCore/std/string/string.h>
 #include <AzCore/std/string/fixed_string.h>
 #include <AzCore/std/string/fixed_string.h>
@@ -24,9 +26,6 @@ namespace AZ
 {
 {
     namespace Utils
     namespace Utils
     {
     {
-        // Common cross platform Utils go here
-        inline constexpr size_t MaxPathLength = 1024;
-
         //! Protects from allocating too much memory. The choice of a 1MB threshold is arbitrary.
         //! Protects from allocating too much memory. The choice of a 1MB threshold is arbitrary.
         //! If you need to work with larger files, please use AZ::IO directly instead of these utility functions.
         //! If you need to work with larger files, please use AZ::IO directly instead of these utility functions.
         inline constexpr size_t DefaultMaxFileSize = 1024 * 1024;
         inline constexpr size_t DefaultMaxFileSize = 1024 * 1024;
@@ -77,10 +76,22 @@ namespace AZ
         //! @returns a result object that indicates if the executable directory was able to be stored within the buffer
         //! @returns a result object that indicates if the executable directory was able to be stored within the buffer
         ExecutablePathResult GetExecutableDirectory(char* exeStorageBuffer, size_t exeStorageSize);
         ExecutablePathResult GetExecutableDirectory(char* exeStorageBuffer, size_t exeStorageSize);
 
 
+        //! Retrieves the full path to the engine from settings registry
+        AZ::IO::FixedMaxPathString GetEnginePath();
+
+        //! Retrieves the full path to the project from settings registry
+        AZ::IO::FixedMaxPathString GetProjectPath();
+
+        //! Retrieves the project name from the settings registry
+        AZ::SettingsRegistryInterface::FixedValueString GetProjectName();
+
+        //! Retrieves the full path where the manifest file lives, i.e. "<userhome>/.o3de/o3de_manifest.json"
+        AZ::IO::FixedMaxPathString GetEngineManifestPath();
+
         //! Retrieves the App root path to use on the current platform
         //! Retrieves the App root path to use on the current platform
         //! If the optional is not engaged the AppRootPath should be calculated based
         //! If the optional is not engaged the AppRootPath should be calculated based
         //! on the location of the bootstrap.cfg file
         //! on the location of the bootstrap.cfg file
-        AZStd::optional<AZStd::fixed_string<MaxPathLength>> GetDefaultAppRootPath();
+        AZStd::optional<AZ::IO::FixedMaxPathString> GetDefaultAppRootPath();
 
 
         //! Retrieves the development write storage path to use on the current platform, may be considered
         //! Retrieves the development write storage path to use on the current platform, may be considered
         //! temporary or cache storage
         //! temporary or cache storage
@@ -88,7 +99,7 @@ namespace AZ
 
 
         // Attempts the supplied path to an absolute path.
         // Attempts the supplied path to an absolute path.
         //! Returns nullopt if path cannot be converted to an absolute path
         //! Returns nullopt if path cannot be converted to an absolute path
-        AZStd::optional<AZStd::fixed_string<MaxPathLength>> ConvertToAbsolutePath(AZStd::string_view path);
+        AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path);
 
 
         //! Save a string to a file. Otherwise returns a failure with error message.
         //! Save a string to a file. Otherwise returns a failure with error message.
         AZ::Outcome<void, AZStd::string> WriteFile(AZStd::string_view content, AZStd::string_view filePath);
         AZ::Outcome<void, AZStd::string> WriteFile(AZStd::string_view content, AZStd::string_view filePath);

+ 5 - 0
Code/Framework/AzCore/AzCore/std/string/fixed_string.h

@@ -249,6 +249,11 @@ namespace AZStd
 
 
         constexpr auto swap(basic_fixed_string& rhs) -> void;
         constexpr auto swap(basic_fixed_string& rhs) -> void;
 
 
+        // C++23 contains
+        constexpr auto contains(const basic_fixed_string& other) const -> bool;
+        constexpr auto contains(Element ch) const -> bool;
+        constexpr auto contains(const_pointer s) const -> bool;
+
         constexpr auto find(const basic_fixed_string& rhs, size_type offset = 0) const -> size_type;
         constexpr auto find(const basic_fixed_string& rhs, size_type offset = 0) const -> size_type;
         constexpr auto find(const_pointer ptr, size_type offset, size_type count) const -> size_type;
         constexpr auto find(const_pointer ptr, size_type offset, size_type count) const -> size_type;
         constexpr auto find(const_pointer ptr, size_type offset = 0) const -> size_type;
         constexpr auto find(const_pointer ptr, size_type offset = 0) const -> size_type;

+ 17 - 0
Code/Framework/AzCore/AzCore/std/string/fixed_string.inl

@@ -1072,6 +1072,23 @@ namespace AZStd
         Traits::assign(rhs.m_buffer[rhs.m_size], Element{ 0 });
         Traits::assign(rhs.m_buffer[rhs.m_size], Element{ 0 });
     }
     }
 
 
+    // C++23 contains
+    template<class Element, size_t MaxElementCount, class Traits>
+    inline constexpr auto basic_fixed_string<Element, MaxElementCount, Traits>::contains(const basic_fixed_string& other) const -> bool
+    {
+        return find(other) != npos;
+    }
+    template<class Element, size_t MaxElementCount, class Traits>
+    inline constexpr auto basic_fixed_string<Element, MaxElementCount, Traits>::contains(value_type c) const -> bool
+    {
+        return find(c) != npos;
+    }
+    template<class Element, size_t MaxElementCount, class Traits>
+    inline constexpr auto basic_fixed_string<Element, MaxElementCount, Traits>::contains(const_pointer s) const -> bool
+    {
+        return find(s) != npos;
+    }
+
     template<class Element, size_t MaxElementCount, class Traits>
     template<class Element, size_t MaxElementCount, class Traits>
     inline constexpr auto basic_fixed_string<Element, MaxElementCount, Traits>::find(const basic_fixed_string& rhs, size_type offset) const -> size_type
     inline constexpr auto basic_fixed_string<Element, MaxElementCount, Traits>::find(const basic_fixed_string& rhs, size_type offset) const -> size_type
     {
     {

+ 16 - 0
Code/Framework/AzCore/AzCore/std/string/string.h

@@ -961,6 +961,22 @@ namespace AZStd
             }
             }
         }
         }
 
 
+        // C++23 contains
+        bool contains(const basic_string& other) const
+        {
+            return find(other) != npos;
+        }
+
+        bool contains(value_type c) const
+        {
+            return find(c) != npos;
+        }
+
+        bool contains(const_pointer s) const
+        {
+            return find(s) != npos;
+        }
+
         inline size_type find(const this_type& rhs, size_type offset = 0) const
         inline size_type find(const this_type& rhs, size_type offset = 0) const
         {
         {
             const_pointer rhsData = SSO_BUF_SIZE <= rhs.m_capacity ? rhs.m_data : rhs.m_buffer;
             const_pointer rhsData = SSO_BUF_SIZE <= rhs.m_capacity ? rhs.m_data : rhs.m_buffer;

+ 16 - 0
Code/Framework/AzCore/AzCore/std/string/string_view.h

@@ -669,6 +669,22 @@ namespace AZStd
             return ends_with(basic_string_view(suffix));
             return ends_with(basic_string_view(suffix));
         }
         }
 
 
+        // C++23 contains
+        constexpr bool contains(basic_string_view other) const
+        {
+            return find(other) != npos;
+        }
+
+        constexpr bool contains(value_type c) const
+        {
+            return find(c) != npos;
+        }
+
+        constexpr bool contains(const_pointer s) const
+        {
+            return find(s) != npos;
+        }
+
         // find
         // find
         constexpr size_type find(basic_string_view other, size_type pos = 0) const
         constexpr size_type find(basic_string_view other, size_type pos = 0) const
         {
         {

+ 5 - 5
Code/Framework/AzCore/Platform/Android/AzCore/Utils/Utils_Android.cpp

@@ -52,10 +52,10 @@ namespace AZ
         // in non-release builds.
         // in non-release builds.
         // If a bootstrap.cfg file is not found in the public storage, it is then searched for
         // If a bootstrap.cfg file is not found in the public storage, it is then searched for
         // within the APK itself
         // within the APK itself
-        AZStd::optional<AZStd::fixed_string<MaxPathLength>> GetDefaultAppRootPath()
+        AZStd::optional<AZ::IO::FixedMaxPathString> GetDefaultAppRootPath()
         {
         {
             const char* appRoot = AZ::Android::Utils::FindAssetsDirectory();
             const char* appRoot = AZ::Android::Utils::FindAssetsDirectory();
-            return appRoot ? AZStd::make_optional<AZStd::fixed_string<MaxPathLength>>(appRoot) : AZStd::nullopt;
+            return appRoot ? AZStd::make_optional<AZ::IO::FixedMaxPathString>(appRoot) : AZStd::nullopt;
         }
         }
 
 
         AZStd::optional<AZ::IO::FixedMaxPathString> GetDevWriteStoragePath()
         AZStd::optional<AZ::IO::FixedMaxPathString> GetDevWriteStoragePath()
@@ -64,10 +64,10 @@ namespace AZ
             return writeStorage ? AZStd::make_optional<AZ::IO::FixedMaxPathString>(writeStorage) : AZStd::nullopt;
             return writeStorage ? AZStd::make_optional<AZ::IO::FixedMaxPathString>(writeStorage) : AZStd::nullopt;
         }
         }
 
 
-        AZStd::optional<AZStd::fixed_string<MaxPathLength>> ConvertToAbsolutePath(AZStd::string_view path)
+        AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
         {
         {
-            AZStd::fixed_string<MaxPathLength> absolutePath;
-            AZStd::fixed_string<MaxPathLength> srcPath{ path };
+            AZ::IO::FixedMaxPathString absolutePath;
+            AZ::IO::FixedMaxPathString srcPath{ path };
             if (AZ::Android::Utils::IsApkPath(srcPath.c_str()))
             if (AZ::Android::Utils::IsApkPath(srcPath.c_str()))
             {
             {
                 return srcPath;
                 return srcPath;

+ 1 - 0
Code/Framework/AzCore/Platform/Android/platform_android_files.cmake

@@ -64,6 +64,7 @@ set(FILES
     AzCore/Socket/AzSocket_Platform.h
     AzCore/Socket/AzSocket_Platform.h
     ../Common/UnixLike/AzCore/std/time_UnixLike.cpp
     ../Common/UnixLike/AzCore/std/time_UnixLike.cpp
     AzCore/Utils/Utils_Android.cpp
     AzCore/Utils/Utils_Android.cpp
+    ../Common/Unimplemented/AzCore/Utils/Utils_Unimplemented.cpp
     ../../AzCore/Android/AndroidEnv.cpp
     ../../AzCore/Android/AndroidEnv.cpp
     ../../AzCore/Android/AndroidEnv.h
     ../../AzCore/Android/AndroidEnv.h
     ../../AzCore/Android/APKFileHandler.cpp
     ../../AzCore/Android/APKFileHandler.cpp

+ 22 - 0
Code/Framework/AzCore/Platform/Common/Unimplemented/AzCore/Utils/Utils_Unimplemented.cpp

@@ -0,0 +1,22 @@
+/*
+* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+* its licensors.
+*
+* For complete copyright and license terms please see the LICENSE at the root of this
+* distribution (the "License"). All use of this software is governed by the License,
+* or, if provided, by the license below or the license accompanying this file. Do not
+* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*
+*/
+
+#include <AzCore/Utils/Utils.h>
+
+namespace AZ::Utils
+{
+    AZ::IO::FixedMaxPathString GetEngineManifestPath()
+    {
+        return {};
+    }
+    
+} // namespace AZ::Utils

+ 19 - 4
Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/Utils/Utils_UnixLike.cpp

@@ -12,7 +12,7 @@
 
 
 #include <AzCore/Utils/Utils.h>
 #include <AzCore/Utils/Utils.h>
 
 
-#include <stdlib.h>
+#include <cstdlib>
 
 
 namespace AZ
 namespace AZ
 {
 {
@@ -25,10 +25,25 @@ namespace AZ
 
 
         void NativeErrorMessageBox(const char*, const char*) {}
         void NativeErrorMessageBox(const char*, const char*) {}
 
 
-        AZStd::optional<AZStd::fixed_string<MaxPathLength>> ConvertToAbsolutePath(AZStd::string_view path)
+        AZ::IO::FixedMaxPathString GetEngineManifestPath()
         {
         {
-            AZStd::fixed_string<MaxPathLength> absolutePath;
-            AZStd::fixed_string<MaxPathLength> srcPath{ path };
+            if (const char* homePath = std::getenv("HOME"); homePath != nullptr)
+            {
+                AZ::IO::FixedMaxPath path{homePath};
+                if (!path.empty())
+                {
+                    path /= ".o3de";
+                    path /= "o3de_manifest.json";
+                }
+                return path.Native();
+            }
+            return {};
+        }
+
+        AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
+        {
+            AZ::IO::FixedMaxPathString absolutePath;
+            AZ::IO::FixedMaxPathString srcPath{ path };
 
 
             if (char* result = realpath(srcPath.c_str(), absolutePath.data()); result)
             if (char* result = realpath(srcPath.c_str(), absolutePath.data()); result)
             {
             {

+ 4 - 4
Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Utils/Utils_WinAPI.cpp

@@ -47,7 +47,7 @@ namespace AZ
             return result;
             return result;
         }
         }
 
 
-        AZStd::optional<AZStd::fixed_string<MaxPathLength>> GetDefaultAppRootPath()
+        AZStd::optional<AZ::IO::FixedMaxPathString> GetDefaultAppRootPath()
         {
         {
             return AZStd::nullopt;
             return AZStd::nullopt;
         }
         }
@@ -57,10 +57,10 @@ namespace AZ
             return AZStd::nullopt;
             return AZStd::nullopt;
         }
         }
 
 
-        AZStd::optional<AZStd::fixed_string<MaxPathLength>> ConvertToAbsolutePath(AZStd::string_view path)
+        AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
         {
         {
-            AZStd::fixed_string<MaxPathLength> absolutePath;
-            AZStd::fixed_string<MaxPathLength> srcPath{ path };
+            AZ::IO::FixedMaxPathString absolutePath;
+            AZ::IO::FixedMaxPathString srcPath{ path };
             char* result = _fullpath(absolutePath.data(), srcPath.c_str(), absolutePath.capacity());
             char* result = _fullpath(absolutePath.data(), srcPath.c_str(), absolutePath.capacity());
             // Force update of the fixed_string size() value
             // Force update of the fixed_string size() value
             absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
             absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));

+ 1 - 1
Code/Framework/AzCore/Platform/Linux/AzCore/Utils/Utils_Linux.cpp

@@ -45,7 +45,7 @@ namespace AZ
             return result;
             return result;
         }
         }
 
 
-        AZStd::optional<AZStd::fixed_string<MaxPathLength>> GetDefaultAppRootPath()
+        AZStd::optional<AZ::IO::FixedMaxPathString> GetDefaultAppRootPath()
         {
         {
             return AZStd::nullopt;
             return AZStd::nullopt;
         }
         }

+ 1 - 1
Code/Framework/AzCore/Platform/Mac/AzCore/Utils/Utils_Mac.cpp

@@ -16,7 +16,7 @@
 
 
 namespace AZ::Utils
 namespace AZ::Utils
 {
 {
-    AZStd::optional<AZStd::fixed_string<MaxPathLength>> GetDefaultAppRootPath()
+    AZStd::optional<AZ::IO::FixedMaxPathString> GetDefaultAppRootPath()
     {
     {
         return AZStd::nullopt;
         return AZStd::nullopt;
     }
     }

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor