diff --git a/.p4ignore b/.p4ignore
deleted file mode 100644
index a342dd77dd..0000000000
--- a/.p4ignore
+++ /dev/null
@@ -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
\ No newline at end of file
diff --git a/AssetProcessorPlatformConfig.ini b/AssetProcessorPlatformConfig.ini
deleted file mode 100644
index 82cc6d0d1e..0000000000
--- a/AssetProcessorPlatformConfig.ini
+++ /dev/null
@@ -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}
diff --git a/Engine/Registry/AssetProcessorPlatformConfig.setreg b/AssetProcessorPlatformConfig.setreg
similarity index 50%
rename from Engine/Registry/AssetProcessorPlatformConfig.setreg
rename to AssetProcessorPlatformConfig.setreg
index 27fd752210..c075342b98 100644
--- a/Engine/Registry/AssetProcessorPlatformConfig.setreg
+++ b/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": {
"AssetProcessor": {
"Settings": {
@@ -14,27 +33,82 @@
"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",
+ //"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": {
"animsettings": "i_caf",
- "Animations": {
- "SkeletonList.xml": "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 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": {
- "watch": "@ROOT@/@GAMENAME@",
- "display": "@GAMENAME@",
+ "watch": "@PROJECTROOT@",
+ "display": "@PROJECTROOT@",
"recursive": 1,
"order": 0
},
+ // gems will be auto-added from 100 onwards
"ScanFolder Root": {
"watch": "@ROOT@",
"recursive": 0,
@@ -52,6 +126,9 @@
"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\\\\/.*"
},
@@ -61,6 +138,7 @@
"Exclude HoldFiles": {
"pattern": ".*\\\\/Levels\\\\/.*_hold\\\\/.*"
},
+ // note that $ has meaning to regex, so we escape it.
"Exclude TempFiles": {
"pattern": ".*\\\\/\\\\$tmp[0-9]*_.*"
},
@@ -88,6 +166,16 @@
"Exclude CMakeFiles": {
"pattern": ".*\\\\/.*\\\\.cmake"
},
+ "Exclude User": {
+ "pattern": ".*/[Uu]ser/.*"
+ },
+ "Exclude Build": {
+ "pattern": ".*/[Bb]uild/.*"
+ },
+
+ // ------------------------------------------------------------------------------
+ // Large Worlds Test
+ // ------------------------------------------------------------------------------
"Exclude Work In Progress Folders": {
"pattern": ".*\\\\/WIP\\\\/.*"
},
@@ -97,9 +185,112 @@
"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}"
@@ -147,9 +338,12 @@
"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",
@@ -163,8 +357,9 @@
},
"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": 4
+ "version": 5
},
"RC chr": {
"glob": "*.chr",
@@ -188,6 +383,7 @@
"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",
@@ -199,7 +395,7 @@
"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.",
+ "params": "skip",
"tools": "copy"
},
"RC usm": {
@@ -227,6 +423,9 @@
"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",
@@ -272,13 +471,6 @@
"params": "copy",
"version": 1
},
- "RC Editor Slice Copy": {
- "glob": "*.slice",
- "params": "copy",
- "critical": true,
- "productAssetType": "{C62C7A87-9C09-4148-A985-12F2C99C0A45}",
- "priority": 2
- },
"RC node": {
"glob": "*.node",
"params": "copy"
@@ -329,6 +521,7 @@
"glob": "*.ext",
"params": "copy"
},
+ // Copy all pak files except level.pak, level.pak has its own builder.
"RC pak": {
"pattern": "^((?!\\\\/level\\\\.pak).)*\\\\.pak$",
"params": "copy"
@@ -365,15 +558,18 @@
"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"
@@ -383,6 +579,7 @@
"params": "copy",
"productAssetType": "{7A2871B9-5EAB-4DE0-A901-B0D2C6920DDB}"
},
+ // Copy over cooked PhysX heightfield
"RC PhysX HeightField": {
"glob": "*.pxheightfield",
"params": "copy",
@@ -392,8 +589,20 @@
"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}"
}
}
}
}
-}
\ No newline at end of file
+}
diff --git a/AutomatedReview/Jenkinsfile b/AutomatedReview/Jenkinsfile
index 0a3d4ad7e9..ac2c871736 100644
--- a/AutomatedReview/Jenkinsfile
+++ b/AutomatedReview/Jenkinsfile
@@ -119,6 +119,7 @@ def LoadPipelineConfig(String pipelineName, String branchName) {
PullFilesFromGit(PIPELINE_CONFIG_FILE, branchName)
def pipelineConfig = {}
pipelineConfig = readJSON file: PIPELINE_CONFIG_FILE
+ palRm(PIPELINE_CONFIG_FILE)
pipelineConfig.platforms = EMPTY_JSON
// Load the pipeline configs per platform
@@ -137,6 +138,7 @@ def LoadPipelineConfig(String pipelineName, String branchName) {
pipelineConfig.platforms[platform] = EMPTY_JSON
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) {
pipelineConfig.platforms[platform].build_types = readJSON file: build_config_path.toString()
}
+ palRm(build_config_path.toString())
}
}
return pipelineConfig
@@ -202,39 +205,45 @@ def PullFilesFromGit(String filenamePath, String branchName, boolean failIfNotFo
folderPathParts.remove(folderPathParts.size()-1) // remove the filename
def folderPath = folderPathParts.join('/')
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('*')) {
- 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 {
@@ -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) {
- palSh('git lfs uninstall', 'Git LFS Uninstall') // Prevent git from pulling lfs objects during checkout
if(fileExists('.git')) {
// 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')
}
if(fileExists(indexLockFile)) { // if it is still there, remove it
- palRm(indexLockFile, 'Remove index.lock')
+ palRm(indexLockFile)
}
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)
palSh('git rev-parse HEAD > commitid', 'Getting commit id')
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) {
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) {
return {
stage("Teardown") {
@@ -538,6 +556,9 @@ try {
} else {
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) {
// https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/Result.java
diff --git a/AutomatedTesting/CMakeLists.txt b/AutomatedTesting/CMakeLists.txt
index b0e448ed83..b2d9a18c6a 100644
--- a/AutomatedTesting/CMakeLists.txt
+++ b/AutomatedTesting/CMakeLists.txt
@@ -9,4 +9,12 @@
# 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)
diff --git a/AutomatedTesting/Config/Editor.xml b/AutomatedTesting/Config/Editor.xml
deleted file mode 100644
index 03e69401d3..0000000000
--- a/AutomatedTesting/Config/Editor.xml
+++ /dev/null
@@ -1,197 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Config/Game.xml b/AutomatedTesting/Config/Game.xml
deleted file mode 100644
index f00e94a04d..0000000000
--- a/AutomatedTesting/Config/Game.xml
+++ /dev/null
@@ -1,179 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Config/Server.xml b/AutomatedTesting/Config/Server.xml
deleted file mode 100644
index af195f8516..0000000000
--- a/AutomatedTesting/Config/Server.xml
+++ /dev/null
@@ -1,136 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Gem/AssetProcessorGemConfig.ini b/AutomatedTesting/Gem/AssetProcessorGemConfig.ini
deleted file mode 100644
index cc69bfdaa3..0000000000
--- a/AutomatedTesting/Gem/AssetProcessorGemConfig.ini
+++ /dev/null
@@ -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\\/.*
diff --git a/AutomatedTesting/Gem/AssetProcessorGemConfig.setreg b/AutomatedTesting/Gem/AssetProcessorGemConfig.setreg
new file mode 100644
index 0000000000..043774c9cc
--- /dev/null
+++ b/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\\\\/.*"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt
index cb71f7f96a..a787fb84fa 100644
--- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt
@@ -30,6 +30,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
Legacy::CryRenderNULL
AZ::AssetProcessor
AutomatedTesting.Assets
+ COMPONENT
+ Physics
)
ly_add_pytest(
NAME AutomatedTesting::PhysicsTests_Sandbox
@@ -42,6 +44,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
Legacy::CryRenderNULL
AZ::AssetProcessor
AutomatedTesting.Assets
+ COMPONENT
+ Physics
)
endif()
@@ -49,7 +53,7 @@ endif()
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_pytest(
NAME AutomatedTesting::ScriptCanvasTests
- TEST_SUITE main
+ TEST_SUITE periodic
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/scripting/TestSuite_Active.py
TIMEOUT 3600
@@ -58,6 +62,20 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
Legacy::CryRenderNULL
AZ::AssetProcessor
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()
@@ -74,6 +92,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
Legacy::CryRenderNULL
AZ::AssetProcessor
AutomatedTesting.Assets
+ COMPONENT
+ WhiteBox
)
endif()
@@ -108,7 +128,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
AZ::AssetProcessor
AutomatedTesting.Assets
Gem::EditorPythonBindings.Editor
- COMPONENT TestTools
+ COMPONENT TestTools
)
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)
## DynVeg ##
-
ly_add_pytest(
NAME DynamicVegetationTests_Main_NoGPU
TEST_SERIAL
@@ -150,6 +169,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
AutomatedTesting.GameLauncher
AutomatedTesting.Assets
Legacy::CryRenderNULL
+ COMPONENT
+ LargeWorlds
)
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.Assets
Legacy::CryRenderNULL
+ COMPONENT
+ LargeWorlds
)
ly_add_pytest(
@@ -179,10 +202,11 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
Legacy::Editor
AutomatedTesting.Assets
Legacy::CryRenderNULL
+ COMPONENT
+ LargeWorlds
)
## LandscapeCanvas ##
-
ly_add_pytest(
NAME LandscapeCanvasTests_Main
TEST_SERIAL
@@ -194,6 +218,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
Legacy::Editor
AutomatedTesting.Assets
Legacy::CryRenderNULL
+ COMPONENT
+ LargeWorlds
)
## GradientSignal ##
@@ -209,6 +235,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
Legacy::Editor
AutomatedTesting.Assets
Legacy::CryRenderNULL
+ COMPONENT
+ LargeWorlds
)
ly_add_pytest(
@@ -222,6 +250,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
Legacy::Editor
AutomatedTesting.Assets
Legacy::CryRenderNULL
+ COMPONENT
+ LargeWorlds
)
endif()
@@ -239,6 +269,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
Legacy::CryRenderNULL
AZ::AssetProcessor
AutomatedTesting.Assets
+ COMPONENT
+ Editor
)
endif()
diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_all_platforms_setup_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_all_platforms_setup_fixture.py
index 5a85d2de90..e4999a28f8 100644
--- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_all_platforms_setup_fixture.py
+++ b/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]:
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
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())
# 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"]
return resources
diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_external_project_setup_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_external_project_setup_fixture.py
index 0b3b22aaca..553427dd17 100644
--- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_external_project_setup_fixture.py
+++ b/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.asset_processor = lambda: resources["ap_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
resources["external_workspace"] = mock_workspace
diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests_2.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests_2.py
index db6c675bdb..00b04f1847 100644
--- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests_2.py
+++ b/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"
# 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"
# 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
"""
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
asset_processor.run_and_check_output(True, error_search_terms, platforms='notaplatform')
diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests_2.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests_2.py
index 9a7ad478aa..47dfaa6e8a 100644
--- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests_2.py
+++ b/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.process_utils as process_utils
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
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)
# This applies to AP and GameLauncher.exe
time.sleep(CHECK_ALIVE_SECONDS)
- launcher_name = f"{workspace.project.title()}Launcher"
+ launcher_name = f"{workspace.project.title()}.GameLauncher"
# fmt:off
assert process_utils.process_exists(launcher_name, ignore_extensions=True), \
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"
- # 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
# 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,
- scan_folder_pattern="*C4874115*")
+ scan_folder_pattern="*C4874115*",
+ extra_params=test_scan_folder_params)
assert result, "AP GUI failed"
# 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
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
result, _ = asset_processor.gui_process(quitonidle=True)
diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/missing_dependency_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/missing_dependency_tests.py
index 11b760f310..30d73e0e17 100644
--- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/missing_dependency_tests.py
+++ b/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._asset_processor.create_temp_asset_root()
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")
self._asset_processor.add_source_folder_assets(f"{self._workspace.project}\\Slices")
self._asset_processor.add_source_folder_assets(f"{self._workspace.project}\\Materials")
diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/fbx_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/fbx_tests.py
index b40808b2c9..594827ee76 100644
--- a/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/fbx_tests.py
+++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/fbx_tests.py
@@ -597,9 +597,9 @@ class TestsFBX_AllPlatforms(object):
# Load the asset database.
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",
- workspace.project, ASSET_PROCESSOR_PLATFORM_MAP[workspace.asset_processor_platform]))
+ ASSET_PROCESSOR_PLATFORM_MAP[workspace.asset_processor_platform]))
if blackbox_params.scene_debug_file:
debug_graph_path = os.path.join(asset_processor.project_test_cache_folder(), blackbox_params.scene_debug_file)
diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py
index 8c38fbe7ac..e3ef1a3ab4 100644
--- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py
+++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/base.py
@@ -131,8 +131,9 @@ class TestAutomationBase:
crash_info = f.read()
except Exception as 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))
self.test_times[testcase_name] = time.time() - test_starttime
diff --git a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Active.py b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Active.py
index ae9222ab42..8c34f29ebf 100644
--- a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Active.py
+++ b/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
-
-@pytest.mark.SUITE_main
+@pytest.mark.SUITE_periodic
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("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)
-
+
def test_Docking_Pane(self, request, workspace, editor, launcher_platform):
from . import Docking_Pane as 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):
from . import Resizing_Pane as test_module
self._run_test(request, workspace, editor, test_module)
-
diff --git a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Sandbox.py b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Sandbox.py
new file mode 100644
index 0000000000..1ab6a59972
--- /dev/null
+++ b/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
+
+
+@pytest.mark.SUITE_sandbox
+@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
+@pytest.mark.parametrize("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)
diff --git a/AutomatedTesting/Registry/assets_scan_folders.setreg b/AutomatedTesting/Registry/assets_scan_folders.setreg
index 02169bd4d5..5394d381a3 100644
--- a/AutomatedTesting/Registry/assets_scan_folders.setreg
+++ b/AutomatedTesting/Registry/assets_scan_folders.setreg
@@ -3,15 +3,45 @@
{
"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":
[
- "Gems/DevTextures",
- "Gems/PBSreferenceMaterials",
- "Gems/PhysicsEntities",
- "Gems/PhysXSamples",
- "Gems/PrimitiveAssets",
"Gems/UiBasics"
]
}
diff --git a/AutomatedTesting/TestAssets/test_chunks_builder.py b/AutomatedTesting/TestAssets/test_chunks_builder.py
index 06a3e41e8c..04629cb53c 100644
--- a/AutomatedTesting/TestAssets/test_chunks_builder.py
+++ b/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
from scene_api import scene_data as sceneData
+import uuid
def update_manifest(scene):
graph = sceneData.SceneGraph(scene.graph)
@@ -27,7 +28,9 @@ def update_manifest(scene):
sceneManifest = sceneData.SceneManifest()
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_set_origin(meshGroup, None, 0, 0, 0, 1.0)
for meshIndex in range(len(chunkNameList)):
diff --git a/AutomatedTesting/UI/TextureAtlas/sample.texatlas b/AutomatedTesting/UI/TextureAtlas/sample.texatlas
index 0fefadc808..779300a96f 100644
--- a/AutomatedTesting/UI/TextureAtlas/sample.texatlas
+++ b/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
diff --git a/AutomatedTesting/gems.json b/AutomatedTesting/gems.json
deleted file mode 100644
index a7ae802fda..0000000000
--- a/AutomatedTesting/gems.json
+++ /dev/null
@@ -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"
- }
- ]
-}
\ No newline at end of file
diff --git a/BuildReleaseAuxiliaryContent.py b/BuildReleaseAuxiliaryContent.py
index 3d11750f8f..e30a4b50e1 100644
--- a/BuildReleaseAuxiliaryContent.py
+++ b/BuildReleaseAuxiliaryContent.py
@@ -24,12 +24,12 @@ def printMessage(message):
def getCurrentProject():
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:
gameFolderMatch = gameProjectRegex.match(line)
if gameFolderMatch:
- return gameFolderMatch.group(1)
+ return os.path.basename(gameFolderMatch.group(1))
return None
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a43314a83c..801aa0447c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,7 +24,7 @@ endif()
include(cmake/Version.cmake)
if(NOT PROJECT_NAME)
- project(Lumberyard
+ project(O3DE
LANGUAGES C CXX
VERSION ${LY_VERSION_STRING}
)
@@ -83,13 +83,30 @@ endif()
# 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:
-# 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
+# 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()
+# 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
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_delayed_generate_unit_test_module_registry()
diff --git a/Code/CryEngine/Cry3DEngine/3DEngineRender.cpp b/Code/CryEngine/Cry3DEngine/3DEngineRender.cpp
index 94dcd98240..7082bfbd38 100644
--- a/Code/CryEngine/Cry3DEngine/3DEngineRender.cpp
+++ b/Code/CryEngine/Cry3DEngine/3DEngineRender.cpp
@@ -1080,7 +1080,7 @@ void C3DEngine::WorldStreamUpdate()
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");
if (resultsFile != AZ::IO::InvalidHandle)
diff --git a/Code/CryEngine/Cry3DEngine/3dEngine.cpp b/Code/CryEngine/Cry3DEngine/3dEngine.cpp
index ecb028ba4f..42306c865f 100644
--- a/Code/CryEngine/Cry3DEngine/3dEngine.cpp
+++ b/Code/CryEngine/Cry3DEngine/3dEngine.cpp
@@ -952,7 +952,7 @@ void C3DEngine::ProcessStreamingLatencyTest(const CCamera& camIn, CCamera& camOu
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");
if (resultsFile != AZ::IO::InvalidHandle)
diff --git a/Code/CryEngine/Cry3DEngine/3dEngineLoad.cpp b/Code/CryEngine/Cry3DEngine/3dEngineLoad.cpp
index b467d11c77..a3cb04dea0 100644
--- a/Code/CryEngine/Cry3DEngine/3dEngineLoad.cpp
+++ b/Code/CryEngine/Cry3DEngine/3dEngineLoad.cpp
@@ -461,7 +461,7 @@ void C3DEngine::UnloadLevel()
m_ptexIconLowMemoryUsage = nullptr;
m_ptexIconHighMemoryUsage = nullptr;
m_ptexIconEditorConnectedToConsole = nullptr;
-
+
if (m_pOpticsManager && !gEnv->IsEditor())
{
m_pOpticsManager->Reset();
@@ -656,7 +656,7 @@ bool C3DEngine::LoadLevel(const char* szFolderName, const char* szMissionName)
// set default render parameters.
// for some reason this is not done later???
m_pSkyLightManager->UpdateRenderParams();
- }
+ }
// Load LevelData.xml 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
if (GetCVars()->e_StatObjPreload && !gEnv->IsEditor())
{
- if (GetCVars()->e_StatObjPreload == 2)
- {
- GetSystem()->OutputLoadingTimeStats();
- }
-
m_pObjManager->PreloadLevelObjects();
-
- if (GetCVars()->e_StatObjPreload == 2)
- {
- GetSystem()->OutputLoadingTimeStats();
- }
}
std::vector* pStatObjTable = NULL;
diff --git a/Code/CryEngine/Cry3DEngine/LightEntity.cpp b/Code/CryEngine/Cry3DEngine/LightEntity.cpp
index 63bd40ef58..df7f7f901a 100644
--- a/Code/CryEngine/Cry3DEngine/LightEntity.cpp
+++ b/Code/CryEngine/Cry3DEngine/LightEntity.cpp
@@ -317,7 +317,8 @@ int CLightEntity::UpdateGSMLightSourceDynamicShadowFrustum(int nDynamicLodCount,
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 vFocusPos = passInfo.GetCamera().GetPosition() + vCameraDirWithoutDepth * fGSMBoxSize;
diff --git a/Code/CryEngine/Cry3DEngine/Material.cpp b/Code/CryEngine/Cry3DEngine/Material.cpp
index ed71df38ca..b0853db518 100644
--- a/Code/CryEngine/Cry3DEngine/Material.cpp
+++ b/Code/CryEngine/Cry3DEngine/Material.cpp
@@ -117,10 +117,6 @@ CMatInfo::CMatInfo()
ZeroStruct(m_streamZoneInfo);
-#ifdef TRACE_MATERIAL_LEAKS
- m_sLoadingCallstack = GetSystem()->GetLoadingProfilerCallstack();
-#endif
-
// Used to know when a .dccmtl file has been changed,
// requiring the source material to be updated
m_dccMaterialHash = 0;
@@ -341,7 +337,7 @@ ISurfaceType* CMatInfo::GetSurfaceType()
//////////////////////////////////////////////////////////////////////////
void CMatInfo::SetSubMtlCount(int numSubMtl)
{
- AUTO_LOCK(GetSubMaterialResizeLock());
+ AUTO_LOCK(GetSubMaterialResizeLock());
if (numSubMtl > 0)
{
m_Flags |= MTL_FLAG_MULTI_SUBMTL;
@@ -1112,15 +1108,6 @@ void CMatInfo::SetTexelDensityDebug([[maybe_unused]] int mode)
#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)
{
// FUNCTION_PROFILER_3DENGINE;
diff --git a/Code/CryEngine/Cry3DEngine/Material.h b/Code/CryEngine/Cry3DEngine/Material.h
index f11a15e250..bc0546a4e1 100644
--- a/Code/CryEngine/Cry3DEngine/Material.h
+++ b/Code/CryEngine/Cry3DEngine/Material.h
@@ -18,7 +18,6 @@
#include
#if !defined(CONSOLE)
-# define TRACE_MATERIAL_LEAKS
# define SUPPORT_MATERIAL_EDITING
#endif
@@ -203,7 +202,7 @@ public:
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 SetGetMaterialParamVec4(const char* sParamName, Vec4& v, bool bGet, bool allowShaderParam = false, int materialIndex = 0) override;
-
+
void SetDirty(bool dirty = true) override;
bool IsDirty() const override;
@@ -264,11 +263,6 @@ public:
bool IsForwardRenderingRequired();
bool IsNearestCubemapRequired();
- //////////////////////////////////////////////////////////////////////////
- // Debug routines
- //////////////////////////////////////////////////////////////////////////
- virtual const char* GetLoadingCallstack(); // trace leaking materials by callstack
-
void DisableTextureStreaming() override;
virtual void RequestTexturesLoading(const float fMipFactor);
@@ -286,13 +280,6 @@ public:
void SetDccMaterialHash(uint32 hash) override { m_dccMaterialHash = hash; }
virtual CryCriticalSection& GetSubMaterialResizeLock();
-public:
- //////////////////////////////////////////////////////////////////////////
- // for debug purposes
- //////////////////////////////////////////////////////////////////////////
-#ifdef TRACE_MATERIAL_LEAKS
- string m_sLoadingCallstack;
-#endif
private:
friend class CMatMan;
diff --git a/Code/CryEngine/Cry3DEngine/StatObj.h b/Code/CryEngine/Cry3DEngine/StatObj.h
index 4b9f60aeeb..771d7354a5 100644
--- a/Code/CryEngine/Cry3DEngine/StatObj.h
+++ b/Code/CryEngine/Cry3DEngine/StatObj.h
@@ -16,7 +16,6 @@
#pragma once
#if !defined(CONSOLE)
-# define TRACE_CGF_LEAKS
# define SUPPORT_TERRAIN_AO_PRE_COMPUTATIONS
#endif
@@ -337,13 +336,6 @@ public:
std::vector m_chunkBoneIds;
//////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////
- // for debug purposes
- //////////////////////////////////////////////////////////////////////////
-#ifdef TRACE_CGF_LEAKS
- string m_sLoadingCallstack;
-#endif
-
private:
//////////////////////////////////////////////////////////////////////////
// Sub objects.
@@ -419,7 +411,7 @@ public:
virtual unsigned int GetBreakableByGame() { return m_bBreakableByGame; };
//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.
virtual bool IsDeformable() override;
diff --git a/Code/CryEngine/Cry3DEngine/StatObjConstr.cpp b/Code/CryEngine/Cry3DEngine/StatObjConstr.cpp
index a4803f7c5d..c6afbd5707 100644
--- a/Code/CryEngine/Cry3DEngine/StatObjConstr.cpp
+++ b/Code/CryEngine/Cry3DEngine/StatObjConstr.cpp
@@ -56,10 +56,6 @@ CStatObj::CStatObj()
m_fLodDistance = 0.0f;
Init();
-
-#ifdef TRACE_CGF_LEAKS
- m_sLoadingCallstack = GetSystem()->GetLoadingProfilerCallstack();
-#endif
}
//////////////////////////////////////////////////////////////////////////
diff --git a/Code/CryEngine/CryCommon/IAudioSystem.h b/Code/CryEngine/CryCommon/IAudioSystem.h
index c2edb36d90..0e68ae88d4 100644
--- a/Code/CryEngine/CryCommon/IAudioSystem.h
+++ b/Code/CryEngine/CryCommon/IAudioSystem.h
@@ -1064,7 +1064,7 @@ namespace Audio
///////////////////////////////////////////////////////////////////////////////////////////
// Interface methods
- virtual bool Initialize(const SSystemInitParams* initParams) = 0;
+ virtual bool Initialize() = 0;
virtual void Release() = 0;
};
diff --git a/Code/CryEngine/CryCommon/IMaterial.h b/Code/CryEngine/CryCommon/IMaterial.h
index f611b2179c..81d612397f 100644
--- a/Code/CryEngine/CryCommon/IMaterial.h
+++ b/Code/CryEngine/CryCommon/IMaterial.h
@@ -392,7 +392,7 @@ struct IMaterial
virtual void SetDirty(bool dirty = true) = 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;
//! Returns true if the material is a single material belongs to a material group
@@ -411,11 +411,6 @@ struct IMaterial
// - 2, fast sketch mode.
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
// If a stream is already in process, this will stop the stream and flush the device texture
virtual void DisableTextureStreaming() = 0;
diff --git a/Code/CryEngine/CryCommon/ISystem.h b/Code/CryEngine/CryCommon/ISystem.h
index 04eb36b008..679dc66327 100644
--- a/Code/CryEngine/CryCommon/ISystem.h
+++ b/Code/CryEngine/CryCommon/ISystem.h
@@ -119,8 +119,6 @@ namespace AZ
class IResourceCompilerHelper;
-class CBootProfilerRecord;
-
namespace Serialization {
struct IArchiveHost;
}
@@ -629,15 +627,7 @@ struct SSystemInitParams
void* hWnd; //
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 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.
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
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 bPreview; // When running in Preview mode (Minimal initialization).
bool bTestMode; // When running in Automated testing mode.
@@ -730,26 +681,7 @@ struct SSystemInitParams
hWnd = 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;
- connectToRemote = false;
- waitForConnection = false;
pLog = NULL;
pLogCallback = NULL;
@@ -762,7 +694,6 @@ struct SSystemInitParams
pValidator = NULL;
pPrintSync = NULL;
memset(szSystemCmdLine, 0, sizeof(szSystemCmdLine));
- memset(szBinariesDir, 0, sizeof(szBinariesDir));
bEditor = false;
bPreview = false;
@@ -798,17 +729,6 @@ struct SSystemInitParams
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:
@@ -1228,11 +1148,6 @@ struct ISystem
// Gets number of CPUs
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:
// Return the rendering driver name. GL or Metal
virtual const char* GetRenderingDriverName() const = 0;
@@ -1406,43 +1321,6 @@ struct ISystem
// True if system running in Test mode.
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.
//////////////////////////////////////////////////////////////////////////
@@ -1581,10 +1459,10 @@ struct ISystem
//////////////////////////////////////////////////////////////////////////
// Summary:
- // Enable/Disable drawing the console
+ // Enable/Disable drawing the console
virtual void SetConsoleDrawEnabled(bool enabled) = 0;
- // Enable/Disable drawing the UI
+ // Enable/Disable drawing the UI
virtual void SetUIDrawEnabled(bool enabled) = 0;
// Summary:
@@ -1772,79 +1650,19 @@ struct DiskOperationInfo
#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_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_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
#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_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
@@ -1865,7 +1683,7 @@ extern SC_API SSystemGlobalEnvironment* gEnv;
inline ISystem* GetISystem()
{
// 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.
// 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.
diff --git a/Code/CryEngine/CryCommon/MaterialUtils.h b/Code/CryEngine/CryCommon/MaterialUtils.h
index 87d2098e3e..901a517094 100644
--- a/Code/CryEngine/CryCommon/MaterialUtils.h
+++ b/Code/CryEngine/CryCommon/MaterialUtils.h
@@ -15,10 +15,12 @@
#include
#include // for max path len
-#include
#include
+#include
#include
+#include
+
namespace MaterialUtils
{
//! 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 };
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)
diff --git a/Code/CryEngine/CryCommon/Mocks/ISystemMock.h b/Code/CryEngine/CryCommon/Mocks/ISystemMock.h
index ca4b838a63..5edd84fd75 100644
--- a/Code/CryEngine/CryCommon/Mocks/ISystemMock.h
+++ b/Code/CryEngine/CryCommon/Mocks/ISystemMock.h
@@ -55,8 +55,6 @@ public:
int());
MOCK_METHOD0(GetLogicalCPUCount,
int());
- MOCK_CONST_METHOD0(GetAssetsPlatform,
- const char*());
MOCK_CONST_METHOD0(GetRenderingDriverName,
const char*());
MOCK_METHOD1(DumpMemoryUsageStatistics,
@@ -206,22 +204,6 @@ public:
bool());
MOCK_METHOD3(SetFrameProfiler,
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,
const SFileVersion&());
MOCK_METHOD0(GetProductVersion,
diff --git a/Code/CryEngine/CryCommon/ParseEngineConfig.h b/Code/CryEngine/CryCommon/ParseEngineConfig.h
deleted file mode 100644
index 0eef1d7769..0000000000
--- a/Code/CryEngine/CryCommon/ParseEngineConfig.h
+++ /dev/null
@@ -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
-#include
-#include
-#include
-#include
-
-// 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(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());
- }
-
- }
-};
diff --git a/Code/CryEngine/CryCommon/ProjectDefines.h b/Code/CryEngine/CryCommon/ProjectDefines.h
index 211e3fcd94..9308412c15 100644
--- a/Code/CryEngine/CryCommon/ProjectDefines.h
+++ b/Code/CryEngine/CryCommon/ProjectDefines.h
@@ -293,7 +293,7 @@ typedef uint32 vtx_idx;
#if defined(ENABLE_PROFILING_CODE)
# 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
#if defined(SOFTCODE_ENABLED)
diff --git a/Code/CryEngine/CryCommon/crycommon_files.cmake b/Code/CryEngine/CryCommon/crycommon_files.cmake
index 1d1ce19db7..8508180994 100644
--- a/Code/CryEngine/CryCommon/crycommon_files.cmake
+++ b/Code/CryEngine/CryCommon/crycommon_files.cmake
@@ -110,7 +110,6 @@ set(FILES
AzDXGIFormat.h
SFunctor.h
FunctorBaseFunction.h
- ParseEngineConfig.h
CustomMemoryHeap.h
FunctorBaseMember.h
stridedptr.h
diff --git a/Code/CryEngine/CrySystem/BootProfiler.cpp b/Code/CryEngine/CrySystem/BootProfiler.cpp
deleted file mode 100644
index edfe87d0cd..0000000000
--- a/Code/CryEngine/CrySystem/BootProfiler.cpp
+++ /dev/null
@@ -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
-#include
-
-
-namespace
-{
- StaticInstance> 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 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("&", "&");
- label.replace("<", "<");
- label.replace(">", ">");
- label.replace("\"", """);
- label.replace("'", "'");
-
- if (m_args.size() > 0)
- {
- m_args.replace("&", "&");
- m_args.replace("<", "<");
- m_args.replace(">", ">");
- m_args.replace("\"", """);
- m_args.replace("'", "'");
- m_args.replace("%", "%");
- }
-
- sprintf_s(buf, buf_size, "%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\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, "\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 \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\n");
- AZ::IO::Print(fileHandle, buf);
- }
- }
-
- sprintf_s(buf, buf_size, "\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 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 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 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 recordGuard{ m_recordMutex };
- if (m_pCurrentSession)
- {
- return m_pCurrentSession->StartBlock(name, args);
- }
- return NULL;
-}
-
-void CBootProfiler::StopBlock(CBootProfilerRecord* record)
-{
- AZStd::lock_guard recordGuard{ m_recordMutex };
- if (m_pCurrentSession)
- {
- m_pCurrentSession->StopBlock(record);
- }
-}
-
-void CBootProfiler::StartFrame(const char* name)
-{
- AZStd::lock_guard recordGuard{ m_recordMutex };
- if (CV_sys_bp_frames)
- {
- StartSession("frames");
- m_pFrameRecord = StartBlock(name, NULL);
- }
-}
-
-void CBootProfiler::StopFrame()
-{
- AZStd::lock_guard 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
diff --git a/Code/CryEngine/CrySystem/BootProfiler.h b/Code/CryEngine/CrySystem/BootProfiler.h
deleted file mode 100644
index ad097257a6..0000000000
--- a/Code/CryEngine/CrySystem/BootProfiler.h
+++ /dev/null
@@ -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
-#include
-#include
-
-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 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
diff --git a/Code/CryEngine/CrySystem/DebugCallStack.cpp b/Code/CryEngine/CrySystem/DebugCallStack.cpp
index fee3e2bf53..789bf64844 100644
--- a/Code/CryEngine/CrySystem/DebugCallStack.cpp
+++ b/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);
WriteLineToLog("Exception: %s, at Address: %s", excCode, excAddr);
- if (CSystem* pSystem = (CSystem*)GetSystem())
- {
- if (const char* pLoadingProfilerCallstack = pSystem->GetLoadingProfilerCallstack())
- {
- if (pLoadingProfilerCallstack[0])
- {
- WriteLineToLog(" LoadingProfilerCallstack: %s", pLoadingProfilerCallstack);
- }
- }
- }
-
{
IMemoryManager::SProcessMemInfo memInfo;
if (gEnv->pSystem->GetIMemoryManager()->GetProcessMemInfo(memInfo))
@@ -593,7 +582,7 @@ void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
AZ::Debug::SymbolStorage::DecodeFrames(frames, numFrames, lines);
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]);
}
}
}
diff --git a/Code/CryEngine/CrySystem/IDebugCallStack.cpp b/Code/CryEngine/CrySystem/IDebugCallStack.cpp
index 178bbf0544..8394da6463 100644
--- a/Code/CryEngine/CrySystem/IDebugCallStack.cpp
+++ b/Code/CryEngine/CrySystem/IDebugCallStack.cpp
@@ -20,8 +20,8 @@
#include "System.h"
#include
#include
-
-#include
+#include
+#include
//#if !defined(LINUX)
#include
@@ -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
GetModuleFileNameA(NULL, s, sizeof(s));
// Log EXE filename only if possible (not full EXE path which could contain sensitive info)
AZStd::string exeName;
- if (AzFramework::StringFunc::Path::GetFullFileName(s, exeName))
+ if (AZ::StringFunc::Path::GetFullFileName(s, exeName))
{
azstrcat(str, length, "Executable: ");
azstrcat(str, length, exeName.c_str());
diff --git a/Code/CryEngine/CrySystem/LoadingProfiler.cpp b/Code/CryEngine/CrySystem/LoadingProfiler.cpp
deleted file mode 100644
index c736dce8cd..0000000000
--- a/Code/CryEngine/CrySystem/LoadingProfiler.cpp
+++ /dev/null
@@ -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 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 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 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& profilers)
-{
- UpdateSelfStatistics(m_pRoot[m_iActiveRoot]);
-
- PodArray 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& 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& 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 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
diff --git a/Code/CryEngine/CrySystem/LoadingProfiler.h b/Code/CryEngine/CrySystem/LoadingProfiler.h
deleted file mode 100644
index b90139364e..0000000000
--- a/Code/CryEngine/CrySystem/LoadingProfiler.h
+++ /dev/null
@@ -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&);
- 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& 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*);
-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
diff --git a/Code/CryEngine/CrySystem/NotificationNetwork.cpp b/Code/CryEngine/CrySystem/NotificationNetwork.cpp
index e50c7284c9..f06f0634c0 100644
--- a/Code/CryEngine/CrySystem/NotificationNetwork.cpp
+++ b/Code/CryEngine/CrySystem/NotificationNetwork.cpp
@@ -16,6 +16,7 @@
#include
#include
+#include
#undef LockDebug
//#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
- 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;
}
- pNotificationNetwork->Send("SystemInfo", path, ::strlen(path) + 1);
+ pNotificationNetwork->Send("SystemInfo", projectPath.c_str(), projectPath.size());
}
} g_queryNotification;
diff --git a/Code/CryEngine/CrySystem/StreamEngine/StreamEngine.cpp b/Code/CryEngine/CrySystem/StreamEngine/StreamEngine.cpp
index 057549e071..3163847b13 100644
--- a/Code/CryEngine/CrySystem/StreamEngine/StreamEngine.cpp
+++ b/Code/CryEngine/CrySystem/StreamEngine/StreamEngine.cpp
@@ -1243,7 +1243,7 @@ namespace
{
char path[AZ::IO::IArchive::MaxPath];
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;
}
AZ::IO::HandleType fileHandle = fxopen(sFileName, (bFirstTime) ? "wt" : "at");
diff --git a/Code/CryEngine/CrySystem/System.cpp b/Code/CryEngine/CrySystem/System.cpp
index 3739c1be11..285f5c2573 100644
--- a/Code/CryEngine/CrySystem/System.cpp
+++ b/Code/CryEngine/CrySystem/System.cpp
@@ -157,7 +157,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
#include "ServerThrottle.h"
#include "ILocalMemoryUsage.h"
#include "ResourceManager.h"
-#include "LoadingProfiler.h"
#include "HMDBus.h"
#include "OverloadSceneManager/OverloadSceneManager.h"
#include
@@ -168,7 +167,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
#include "IZStdDecompressor.h"
#include "zlib.h"
#include "RemoteConsole/RemoteConsole.h"
-#include "BootProfiler.h"
#include
#include
@@ -320,10 +318,6 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
m_bIsAsserting = false;
m_pSystemEventDispatcher = new CSystemEventDispatcher(); // Must be first.
-#if defined(ENABLE_LOADING_PROFILER)
- CBootProfiler::GetInstance().Init(this);
-#endif
-
if (m_pSystemEventDispatcher)
{
m_pSystemEventDispatcher->RegisterListener(this);
@@ -422,7 +416,6 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
// m_sys_filecache = NULL;
m_gpu_particle_physics = NULL;
m_pCpu = NULL;
- m_sys_game_folder = NULL;
m_bInitializedSuccessfully = false;
m_bShaderCacheGenMode = false;
@@ -634,10 +627,6 @@ void CSystem::ShutDown()
EBUS_EVENT(CrySystemEventBus, OnCrySystemShutdown, *this);
}
-#if defined(ENABLE_LOADING_PROFILER)
- CLoadingProfilerSystem::ShutDown();
-#endif
-
if (m_pUserCallback)
{
m_pUserCallback->OnShutdown();
@@ -657,7 +646,7 @@ void CSystem::ShutDown()
SAFE_DELETE(m_pTextModeConsole);
KillPhysicsThread();
-
+
if (m_sys_firstlaunch)
{
m_sys_firstlaunch->Set("0");
@@ -828,7 +817,7 @@ void CSystem::ShutDown()
void CSystem::Quit()
{
CryLogAlways("CSystem::Quit invoked from thread %" PRI_THREADID " (main is %" PRI_THREADID ")", GetCurrentThreadId(), gEnv->mMainThreadId);
-
+
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
@@ -857,13 +846,13 @@ void CSystem::Quit()
/*
* 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
* 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.
*/
#if defined(AZ_RESTRICTED_PLATFORM)
@@ -1117,7 +1106,7 @@ void CSystem::CreatePhysicsThread()
#include AZ_RESTRICTED_FILE(System_cpp)
#endif
- {
+ {
m_PhysThread = new CPhysicsThreadTask;
GetIThreadTaskManager()->RegisterTask(m_PhysThread, threadParams);
}
@@ -1412,7 +1401,7 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
ti.xscale = ti.yscale = 1.2f;
const int viewportHeight = GetViewCamera().GetViewSurfaceZ();
-
+
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION SYSTEM_CPP_SECTION_8
#include AZ_RESTRICTED_FILE(System_cpp)
@@ -1428,7 +1417,7 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
switch (stat.GetType())
{
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());
break;
case AZ::IO::Statistic::Type::Integer:
@@ -2744,10 +2733,10 @@ bool CSystem::HandleMessage([[maybe_unused]] HWND hWnd, UINT uMsg, WPARAM wParam
{
// System event translation
case WM_CLOSE:
- /*
+ /*
Trigger CSystem to call Quit() the next time
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
cause the render thread to deadlock and the main
thread to spin in SRenderThread::WaitFlushFinishedCond.
@@ -2897,11 +2886,6 @@ std::shared_ptr CSystem::CreateLocalFileIO()
return std::make_shared();
}
-const char* CSystem::GetAssetsPlatform() const
-{
- return m_assetPlatform.c_str();
-}
-
IViewSystem* CSystem::GetIViewSystem()
{
return m_pViewSystem;
diff --git a/Code/CryEngine/CrySystem/System.h b/Code/CryEngine/CrySystem/System.h
index 47ea7133d5..1244283f7d 100644
--- a/Code/CryEngine/CrySystem/System.h
+++ b/Code/CryEngine/CrySystem/System.h
@@ -45,7 +45,6 @@ struct IConsoleCmdArgs;
class CServerThrottle;
struct ICryFactoryRegistryImpl;
struct IZLibCompressor;
-class CLoadingProfilerSystem;
class CWatchdogThread;
class CThreadManager;
@@ -437,11 +436,6 @@ public:
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 DumpMemoryCoverage();
void CollectMemInfo(SCryEngineStatsGlobalMemInfo&);
@@ -685,7 +679,7 @@ private:
bool InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInitParams& initParams);
bool InitFont(const SSystemInitParams& initParams);
- bool InitFileSystem(const SSystemInitParams& initParams);
+ bool InitFileSystem();
bool InitFileSystem_LoadEngineFolders(const SSystemInitParams& initParams);
bool InitStreamEngine();
bool Init3DEngine(const SSystemInitParams& initParams);
@@ -792,7 +786,7 @@ public:
const CTimeValue& GetLastTickTime(void) const { return m_lastTickTime; }
const ICVar* GetDedicatedMaxRate(void) const { return m_svDedicatedMaxRate; }
-
+
const char* GetRenderingDriverName(void) const
{
if(m_rDriver)
@@ -802,7 +796,7 @@ public:
return nullptr;
}
-
+
std::shared_ptr CreateLocalFileIO();
// Gets the dimensions (in pixels) of the primary physical display.
@@ -914,7 +908,6 @@ private: // ------------------------------------------------------
// DLL names
ICVar* m_sys_dll_response_system;
- ICVar* m_sys_game_folder;
#if !defined(_RELEASE)
ICVar* m_sys_resource_cache_folder;
#endif
@@ -950,7 +943,6 @@ private: // ------------------------------------------------------
ICVar* m_rFullscreenWindow;
ICVar* m_rFullscreenNativeRes;
ICVar* m_rDriver;
- ICVar* m_cvGameName;
ICVar* m_rDisplayInfo;
ICVar* m_rOverscanBordersDrawDebugView;
ICVar* m_sysNoUpdate;
@@ -1040,8 +1032,6 @@ private: // ------------------------------------------------------
uint64 m_nUpdateCounter;
- int sys_ProfileLevelLoading, sys_ProfileLevelLoadingDump;
-
bool m_executedCommandLine = false;
AZStd::unique_ptr m_missingAssetLogger;
@@ -1072,18 +1062,6 @@ public:
void CloseLanguageAudioPak(const char* sLanguage);
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.
virtual bool RegisterErrorObserver(IErrorObserver* errorObserver);
@@ -1139,17 +1117,9 @@ protected: // -------------------------------------------------------------
ITextModeConsole* m_pTextModeConsole;
INotificationNetwork* m_pNotificationNetwork;
- string m_binariesDir;
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
- // 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 > m_updateTimes;
CMemoryFragmentationProfiler m_MemoryFragmentationProfiler;
diff --git a/Code/CryEngine/CrySystem/SystemCFG.cpp b/Code/CryEngine/CrySystem/SystemCFG.cpp
index 16880a2f39..573056370f 100644
--- a/Code/CryEngine/CrySystem/SystemCFG.cpp
+++ b/Code/CryEngine/CrySystem/SystemCFG.cpp
@@ -23,6 +23,7 @@
#include
#include
+#include
#include
#include "SystemCFG.h"
@@ -252,15 +253,8 @@ void CSystem::LogVersion()
//////////////////////////////////////////////////////////////////////////
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__);
}
diff --git a/Code/CryEngine/CrySystem/SystemInit.cpp b/Code/CryEngine/CrySystem/SystemInit.cpp
index 3dad415d99..5fcf63a2ef 100644
--- a/Code/CryEngine/CrySystem/SystemInit.cpp
+++ b/Code/CryEngine/CrySystem/SystemInit.cpp
@@ -68,6 +68,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -115,8 +116,6 @@
#include "SystemCFG.h"
#include "AutoDetectSpec.h"
#include "ResourceManager.h"
-#include "LoadingProfiler.h"
-#include "BootProfiler.h"
#include "VisRegTest.h"
#include "MTSafeAllocator.h"
#include "NotificationNetwork.h"
@@ -498,7 +497,7 @@ struct SysSpecOverrideSinkConsole
else
{
// 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.
gEnv->pConsole->LoadConfigVar(szKey, szValue);
}
@@ -618,13 +617,13 @@ static void LoadDetectedSpec(ICVar* pVar)
if (gEnv->IsEditor())
{
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)
{
platform = configPlatform;
}
}
-
+
AZStd::string configFile;
GetSpecConfigFileToLoad(pVar, configFile, platform);
if (configFile.length())
@@ -779,7 +778,7 @@ static void LoadDetectedSpec(ICVar* pVar)
MobileSysInspect::GetSpecForGPUAndAPI(adapterDesc, apiver, gpuConfigFile);
GetISystem()->LoadConfiguration(gpuConfigFile.c_str(), pSysSpecOverrideSinkConsole);
}
-#endif
+#endif
}
if (bMultiGPUEnabled)
{
@@ -832,23 +831,7 @@ AZStd::unique_ptr CSystem::LoadDynamiclibrary(const cha
{
AZStd::unique_ptr 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
InjectEnvironmentFunction injectEnv = handle->GetFunction(INJECT_ENVIRONMENT_FUNCTION);
if (injectEnv)
@@ -974,7 +957,7 @@ bool CSystem::InitializeEngineModule(const char* dllName, const char* moduleClas
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
-#else
+#else
dllfile.append(dllName);
@@ -1007,7 +990,7 @@ bool CSystem::InitializeEngineModule(const char* dllName, const char* moduleClas
if (CryCreateClassInstance(moduleClassName, pModule))
{
bResult = pModule->Initialize(m_env, initParams);
-
+
// After initializing the module, give it a chance to register any AZ console vars
// declared within the module.
pModule->RegisterConsoleVars();
@@ -1453,7 +1436,7 @@ bool CSystem::InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInit
displayWidth *= scaleFactor;
displayHeight *= scaleFactor;
-
+
const int maxWidth = m_rMaxWidth->GetIVal();
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;
using namespace AzFramework::AssetSystem;
@@ -1549,136 +1532,6 @@ bool CSystem::InitFileSystem(const SSystemInitParams& initParams)
}
#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::Get();
m_env.pFileIO = AZ::IO::FileIOBase::GetInstance();
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)
{
LOADING_TIME_PROFILE_SECTION;
- // Load value of sys_game_folder from system.cfg into the sys_game_folder console variable
{
ILoadConfigurationEntrySink* pCVarsWhiteListConfigSink = GetCVarsWhiteListConfigSink();
LoadConfiguration(m_systemConfigName.c_str(), pCVarsWhiteListConfigSink);
@@ -1767,17 +1619,19 @@ bool CSystem::InitFileSystem_LoadEngineFolders(const SSystemInitParams& initPara
#endif
GetISystem()->SetConfigPlatform(GetDevicePlatform());
-
+
#if defined(CRY_ENABLE_RC_HELPER)
if (!m_env.pResourceCompilerHelper)
{
m_env.pResourceCompilerHelper = new CResourceCompilerHelper();
}
#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
if (!m_pResourceManager->LoadFastLoadPaks(true))
@@ -1857,7 +1711,7 @@ bool CSystem::InitFont(const SSystemInitParams& initParams)
bool CSystem::Init3DEngine(const SSystemInitParams& initParams)
{
LOADING_TIME_PROFILE_SECTION(GetISystem());
-
+
if (!InitializeEngineModule(DLL_3DENGINE, "EngineModule_Cry3DEngine", initParams))
{
return false;
@@ -1930,7 +1784,7 @@ bool CSystem::InitVTuneProfiler()
LOADING_TIME_PROFILE_SECTION(GetISystem());
#ifdef PROFILE_WITH_VTUNE
-
+
WIN_HMODULE hModule = LoadDLL("VTuneApi.dll");
if (!hModule)
{
@@ -2033,7 +1887,7 @@ void CSystem::OpenBasicPaks()
bBasicPaksLoaded = true;
LOADING_TIME_PROFILE_SECTION;
-
+
// open pak files
constexpr AZStd::string_view paksFolder = "@assets@/*.pak"; // (@assets@ assumed)
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)
static wstring GetErrorStringUnsupportedCPU()
{
@@ -2415,8 +2263,8 @@ bool CSystem::Init(const SSystemInitParams& startupParams)
signal(SIGILL, CryEngineSignalHandler);
#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
// to m_env
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!
m_env.bNoAssertDialog = true;
#endif
-
+
m_pCmdLine = new CCmdLine(startupParams.szSystemCmdLine);
AZCoreLogSink::Connect();
@@ -2461,25 +2309,25 @@ bool CSystem::Init(const SSystemInitParams& startupParams)
{
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=" 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.");
@@ -2518,11 +2366,6 @@ AZ_POP_DISABLE_WARNING
m_hInst = (WIN_HINSTANCE)startupParams.hInstance;
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_bPreviewMode = startupParams.bPreview;
m_bTestMode = startupParams.bTestMode;
@@ -2666,17 +2509,13 @@ AZ_POP_DISABLE_WARNING
//////////////////////////////////////////////////////////////////////////
// File system, must be very early
//////////////////////////////////////////////////////////////////////////
- if (!InitFileSystem(startupParams))
+ if (!InitFileSystem())
{
return false;
}
//////////////////////////////////////////////////////////////////////////
InlineInitializationProcessing("CSystem::Init InitFileSystem");
-#if defined(ENABLE_LOADING_PROFILER)
- CLoadingProfilerSystem::Init();
-#endif
-
m_missingAssetLogger = AZStd::make_unique();
//////////////////////////////////////////////////////////////////////////
@@ -2786,10 +2625,6 @@ AZ_POP_DISABLE_WARNING
GetIRemoteConsole()->RegisterConsoleVariables();
-#ifdef ENABLE_LOADING_PROFILER
- CBootProfiler::GetInstance().RegisterCVars();
-#endif
-
if (!startupParams.bSkipConsole)
{
// Register system console variables.
@@ -2827,7 +2662,7 @@ AZ_POP_DISABLE_WARNING
m_env.pCryPak->OpenPack("@assets@", "Engine.pak");
#if defined(AZ_PLATFORM_ANDROID) || defined(AZ_PLATFORM_IOS)
MobileSysInspect::LoadDeviceSpecMapping();
-#endif
+#endif
InitFileSystem_LoadEngineFolders(startupParams);
@@ -3472,10 +3307,6 @@ AZ_POP_DISABLE_WARNING
MarkThisThreadForDebugging("Main");
}
-#if defined(ENABLE_LOADING_PROFILER)
- CLoadingProfilerSystem::SaveTimeContainersToFile("EngineStart.crylp", 0.0, true);
-#endif
-
InlineInitializationProcessing("CSystem::Init End");
#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
void CmdSetAwsLogLevel(IConsoleCmdArgs* pArgs)
{
@@ -4424,7 +4255,6 @@ void CSystem::CreateSystemVars()
// Register DLL names as cvars before we load them
//
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_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.");
#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, "");
m_pCVarQuit = REGISTER_INT("ExitOnQuit", 1, VF_NULL, "");
@@ -4495,7 +4323,7 @@ void CSystem::CreateSystemVars()
}
#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_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"
"Usage: LoadConfig ");
- 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);
m_env.pConsole->CreateKeyBind("alt_keyboard_key_function_F12", "Screenshot");
m_env.pConsole->CreateKeyBind("alt_keyboard_key_function_F11", "RecordClip");
@@ -4871,7 +4690,7 @@ void CSystem::CreateSystemVars()
// adding CVAR to toggle assert verbosity level
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"
"1 = Log Asserts\n"
"2 = Show Assert Dialog\n"
@@ -4957,78 +4776,6 @@ void CSystem::AddCVarGroupDirectory(const string& sPath)
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)
{
return stl::push_back_unique(m_errorObservers, errorObserver);
diff --git a/Code/CryEngine/CrySystem/SystemWin32.cpp b/Code/CryEngine/CrySystem/SystemWin32.cpp
index c6b252124c..8198949359 100644
--- a/Code/CryEngine/CrySystem/SystemWin32.cpp
+++ b/Code/CryEngine/CrySystem/SystemWin32.cpp
@@ -92,13 +92,6 @@ static AZStd::vector GetModuleNames()
moduleNames.push_back("CryFont" 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
# if defined(LINUX)
@@ -1076,14 +1069,6 @@ void CSystem::FatalError(const char* format, ...)
CryLogAlways(" Last System Error: %s", szSysErrorMessage);
}
- if (const char* pLoadingProfilerCallstack = GetLoadingProfilerCallstack())
- {
- if (pLoadingProfilerCallstack[0])
- {
- CryLogAlways(" LoadingProfilerCallstack: %s", pLoadingProfilerCallstack);
- }
- }
-
if (GetUserCallback())
{
GetUserCallback()->OnError(szBuffer);
diff --git a/Code/CryEngine/CrySystem/Tests/Test_BootProfiler.cpp b/Code/CryEngine/CrySystem/Tests/Test_BootProfiler.cpp
deleted file mode 100644
index e7e25d51e9..0000000000
--- a/Code/CryEngine/CrySystem/Tests/Test_BootProfiler.cpp
+++ /dev/null
@@ -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
-#include
-#include
-#include
-#include
-#include
-
-#if defined(ENABLE_LOADING_PROFILER)
-
-namespace UnitTests
-{
- using BootProfilerTestAllocatorScope = AZ::AllocatorScope;
- 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
diff --git a/Code/CryEngine/CrySystem/Tests/test_MaterialUtils.cpp b/Code/CryEngine/CrySystem/Tests/test_MaterialUtils.cpp
index 782587b7b0..99077e41e8 100644
--- a/Code/CryEngine/CrySystem/Tests/test_MaterialUtils.cpp
+++ b/Code/CryEngine/CrySystem/Tests/test_MaterialUtils.cpp
@@ -75,15 +75,10 @@ TEST(CrySystemMaterialUtilsTests, MaterialUtilsTestPrefixes)
TEST(CrySystemMaterialUtilsTests, MaterialUtilsTestGameName)
{
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);
EXPECT_TRUE(strcmp(tempBuffer, "materials/blahblah.mat.mat.abc") == 0);
-}
\ No newline at end of file
+}
diff --git a/Code/CryEngine/CrySystem/UnitTests/CryPakUnitTests.cpp b/Code/CryEngine/CrySystem/UnitTests/CryPakUnitTests.cpp
index fd198371fe..7931acae76 100644
--- a/Code/CryEngine/CrySystem/UnitTests/CryPakUnitTests.cpp
+++ b/Code/CryEngine/CrySystem/UnitTests/CryPakUnitTests.cpp
@@ -60,7 +60,7 @@ namespace CryPakUnitTests
AZ::IO::FileIOBase* fileIo = AZ::IO::FileIOBase::GetInstance();
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 };
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 });
// helper paths and strings
- AZStd::string gameFolder = fileIo->GetAlias("@cache@");
+ AZStd::string gameFolder = fileIo->GetAlias("@usercache@");
AZStd::string testFile = "unittest.bin";
AZStd::string testFilePath = gameFolder + "\\" + testFile;
diff --git a/Code/CryEngine/CrySystem/VisRegTest.cpp b/Code/CryEngine/CrySystem/VisRegTest.cpp
index 27745c62e5..81ef205b47 100644
--- a/Code/CryEngine/CrySystem/VisRegTest.cpp
+++ b/Code/CryEngine/CrySystem/VisRegTest.cpp
@@ -297,7 +297,7 @@ void CVisRegTest::CaptureSample(const SCmd& cmd)
if (m_cmdFreq == 1) // Final sample
{
// 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();
gEnv->pRenderer->ScreenShot(filename);
@@ -335,7 +335,7 @@ void CVisRegTest::Finish()
bool CVisRegTest::WriteResults()
{
- stack_string filename("@cache@/TestResults/VisReg/");
+ stack_string filename("@usercache@/TestResults/VisReg/");
filename += m_testName + "/visreg_results.xml";
AZ::IO::HandleType fileHandle = fxopen(filename.c_str(), "wb");
diff --git a/Code/CryEngine/CrySystem/crysystem_files.cmake b/Code/CryEngine/CrySystem/crysystem_files.cmake
index 422fc221b5..c096a710f6 100644
--- a/Code/CryEngine/CrySystem/crysystem_files.cmake
+++ b/Code/CryEngine/CrySystem/crysystem_files.cmake
@@ -26,7 +26,6 @@ set(FILES
IDebugCallStack.cpp
AsyncPakManager.cpp
Log.cpp
- BootProfiler.cpp
SystemRender.cpp
NotificationNetwork.cpp
PhysRenderer.cpp
@@ -91,7 +90,6 @@ set(FILES
WindowsConsole.h
XConsole.h
XConsoleVariable.h
- BootProfiler.h
crash_face.bmp
ImageHandler.h
ImageHandler.cpp
@@ -121,11 +119,9 @@ set(FILES
XML/WriteXMLSource.cpp
ZipFile.h
ZipFileFormat_info.h
- LoadingProfiler.cpp
PerfHUD.cpp
ProfileLogSystem.cpp
Sampler.cpp
- LoadingProfiler.h
PerfHUD.h
ProfileLogSystem.h
Sampler.h
diff --git a/Code/CryEngine/RenderDll/Common/Renderer.cpp b/Code/CryEngine/RenderDll/Common/Renderer.cpp
index e8591ebb01..41721ec110 100644
--- a/Code/CryEngine/RenderDll/Common/Renderer.cpp
+++ b/Code/CryEngine/RenderDll/Common/Renderer.cpp
@@ -902,7 +902,7 @@ void ShadersOptimizeHelper(CallableT setupParserBin, const char* logString)
{
setupParserBin();
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());
gRenDev->m_cEF.mfOptimiseShaders(str.c_str(), false);
}
@@ -2396,7 +2396,7 @@ void CRenderer::InitRenderer()
CV_r_ShaderCompilerFolderSuffix = REGISTER_STRING("r_ShaderCompilerFolderSuffix", "", VF_NULL,
"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();
diff --git a/Code/CryEngine/RenderDll/Common/Shaders/RemoteCompiler.cpp b/Code/CryEngine/RenderDll/Common/Shaders/RemoteCompiler.cpp
index cf189ff136..8bded3aee3 100644
--- a/Code/CryEngine/RenderDll/Common/Shaders/RemoteCompiler.cpp
+++ b/Code/CryEngine/RenderDll/Common/Shaders/RemoteCompiler.cpp
@@ -20,6 +20,7 @@
#include
#include
#include
+#include
#include
#include
@@ -306,23 +307,20 @@ namespace NRemoteCompiler
m_RequestLineRootFolder = "";
- ICVar* pGameFolder = gEnv->pConsole->GetCVar("sys_game_folder");
+ auto projectName = AZ::Utils::GetProjectName();
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())
diff --git a/Code/CryEngine/RenderDll/Common/Shaders/RemoteShaderCompilerUnitTests.cpp b/Code/CryEngine/RenderDll/Common/Shaders/RemoteShaderCompilerUnitTests.cpp
index 8d32c19998..b0bcf1e702 100644
--- a/Code/CryEngine/RenderDll/Common/Shaders/RemoteShaderCompilerUnitTests.cpp
+++ b/Code/CryEngine/RenderDll/Common/Shaders/RemoteShaderCompilerUnitTests.cpp
@@ -13,16 +13,61 @@
#include
#include
#include
+#include
#include
#include "Mocks/IConsoleMock.h"
#include "Mocks/ICVarMock.h"
#include "Mocks/ISystemMock.h"
#include "RemoteCompiler.h"
+
+namespace AZ
+{
+ class SettingsRegistrySimpleMock;
+ using NiceSettingsRegistrySimpleMock = ::testing::NiceMock;
+
+ 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*));
+ MOCK_METHOD5(
+ MergeSettingsFolder,
+ bool(AZStd::string_view, const Specializations&, AZStd::string_view, AZStd::string_view, AZStd::vector*));
+ };
+} // namespace AZ
+
+
namespace NRemoteCompiler
{
using ::testing::NiceMock;
using ::testing::Return;
+ using ::testing::DoAll;
using SystemAllocatorScope = AZ::AllocatorScope;
@@ -65,9 +110,12 @@ namespace NRemoteCompiler
SystemAllocatorScope::ActivateAllocators();
m_priorEnv = gEnv;
+ m_priorSettingsRegistry = AZ::SettingsRegistry::Get();
m_data.reset(new DataMembers);
+ AZ::SettingsRegistry::Register(&m_data->m_settings);
+
ON_CALL(m_data->m_console, GetCVar(_))
.WillByDefault(Return(&m_data->m_cvarMock));
@@ -89,6 +137,11 @@ namespace NRemoteCompiler
void TearDown() override
{
gEnv = m_priorEnv;
+ AZ::SettingsRegistry::Unregister(&m_data->m_settings);
+ if (m_priorSettingsRegistry)
+ {
+ AZ::SettingsRegistry::Register(m_priorSettingsRegistry);
+ }
m_data.reset();
SystemAllocatorScope::DeactivateAllocators();
AllocatorsTestFixture::TearDown();
@@ -99,12 +152,14 @@ namespace NRemoteCompiler
NiceMock m_system;
NiceMock m_console;
NiceMock m_cvarMock;
+ AZ::NiceSettingsRegistrySimpleMock m_settings;
SSystemGlobalEnvironment m_stubEnv;
};
AZStd::unique_ptr m_data;
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.
@@ -130,7 +185,9 @@ namespace NRemoteCompiler
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;
ShaderSrvUnitTestAccessor srv;
@@ -140,8 +197,10 @@ namespace NRemoteCompiler
TEST_F(RemoteCompilerTest, CShaderSrv_Constructor_WithValidGameName_Succeeds)
{
// 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;
}
@@ -149,11 +208,12 @@ namespace NRemoteCompiler
TEST_F(RemoteCompilerTest, CShaderSrv_EncapsulateRequestInEngineConnectionProtocol_EmptyData_Fails)
{
// 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;
-
std::vector testVector;
@@ -165,11 +225,12 @@ namespace NRemoteCompiler
TEST_F(RemoteCompilerTest, CShaderSrv_EncapsulateRequestInEngineConnectionProtocol_ValidData_EmptyServerList_Fails)
{
// 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;
-
EXPECT_CALL(m_data->m_cvarMock, GetString())
.WillRepeatedly(Return("")); // empty server list
@@ -186,11 +247,12 @@ namespace NRemoteCompiler
TEST_F(RemoteCompilerTest, CShaderSrv_EncapsulateRequestInEngineConnectionProtocol_ValidInputs_Succeeds)
{
// 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;
-
// After this, it will repeatedly call get cvar to get the server address:
const char* testList = "10.20.30.40";
@@ -207,11 +269,12 @@ namespace NRemoteCompiler
TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_EmptyData_Fails)
{
// 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;
-
// After this, it will repeatedly call get cvar to get the server address:
const char* testList = "10.20.30.40";
@@ -221,7 +284,7 @@ namespace NRemoteCompiler
std::vector testVector;
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;
testString = "empty";
testVector.assign(testString.begin(), testString.end());
@@ -232,11 +295,12 @@ namespace NRemoteCompiler
TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_IncompleteData_Fails)
{
// 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;
-
// After this, it will repeatedly call get cvar to get the server address:
const char* testList = "10.20.30.40";
@@ -247,7 +311,7 @@ namespace NRemoteCompiler
std::string testString("incomplete");
testVector.assign(testString.begin(), testString.end());
- // test for incomplete data - recvfailed expected
+ // test for incomplete data - RecvFailed expected
AZ_TEST_START_TRACE_SUPPRESSION;
EXPECT_EQ(srv.SendRequestViaEngineConnection(testVector), EServerError::ESRecvFailed);
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
@@ -256,11 +320,12 @@ namespace NRemoteCompiler
TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_CorruptData_Fails)
{
// 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;
-
// After this, it will repeatedly call get cvar to get the server address:
const char* testList = "10.20.30.40";
@@ -271,7 +336,7 @@ namespace NRemoteCompiler
std::string testString("corrupt");
testVector.assign(testString.begin(), testString.end());
- // test for incomplete data - recvfailed expected
+ // test for incomplete data - RecvFailed expected
AZ_TEST_START_TRACE_SUPPRESSION;
EXPECT_EQ(srv.SendRequestViaEngineConnection(testVector), EServerError::ESRecvFailed);
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
@@ -280,11 +345,12 @@ namespace NRemoteCompiler
TEST_F(RemoteCompilerTest, CShaderSrv_SendRequestViaEngineConnection_CompileError_Fails_ReturnsText)
{
// 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;
-
// After this, it will repeatedly call get cvar to get the server address:
const char* testList = "10.20.30.40";
@@ -294,11 +360,11 @@ namespace NRemoteCompiler
std::vector testVector;
std::string testString("corrupt");
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";
testVector.assign(testString.begin(), testString.end());
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";
EXPECT_EQ(testVector.size(), strlen(expected_decode));
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)
{
// 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;
-
// After this, it will repeatedly call get cvar to get the server address:
const char* testList = "10.20.30.40";
diff --git a/Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp b/Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp
index 8dec38548b..06c1715355 100644
--- a/Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp
+++ b/Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp
@@ -375,7 +375,7 @@ void CShaderMan::mfInitShadersCacheMissLog()
// create valid path
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
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++)
{
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);
if (!pCache || !pCache->m_pRes[CACHE_USER])
diff --git a/Code/CryEngine/RenderDll/Common/Shaders/ShaderCore.cpp b/Code/CryEngine/RenderDll/Common/Shaders/ShaderCore.cpp
index 6fedb3110c..c0d44fcf40 100644
--- a/Code/CryEngine/RenderDll/Common/Shaders/ShaderCore.cpp
+++ b/Code/CryEngine/RenderDll/Common/Shaders/ShaderCore.cpp
@@ -1589,7 +1589,7 @@ void CShaderMan::mfInit (void)
#else
m_ShadersCache = CONCAT_PATHS(g_shaderCache, "D3D11");
#endif
- m_szCachePath = "@cache@/";
+ m_szCachePath = "@usercache@/";
if (CRenderer::CV_r_shadersImport == 3)
{
diff --git a/Code/CryEngine/RenderDll/Common/Shaders/ShaderSerialize.cpp b/Code/CryEngine/RenderDll/Common/Shaders/ShaderSerialize.cpp
index 92185363be..aa457703cd 100644
--- a/Code/CryEngine/RenderDll/Common/Shaders/ShaderSerialize.cpp
+++ b/Code/CryEngine/RenderDll/Common/Shaders/ShaderSerialize.cpp
@@ -162,7 +162,7 @@ bool CShaderSerialize::OpenSResource(const char* szName, SSShaderRes* pSR, CSha
stack_string szReadOnly = szName;
// 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
// 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:
diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/D3DHWShaderCompiling.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/D3DHWShaderCompiling.cpp
index 1f7c484705..b200f3e2bc 100644
--- a/Code/CryEngine/RenderDll/XRenderD3D9/D3DHWShaderCompiling.cpp
+++ b/Code/CryEngine/RenderDll/XRenderD3D9/D3DHWShaderCompiling.cpp
@@ -3490,7 +3490,7 @@ void CHWShader_D3D::mfSaveCGFile(const char* scr, const char* path)
}
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;
@@ -4672,7 +4672,7 @@ bool CAsyncShaderTask::CompileAsyncShader(SShaderAsyncInfo* pAsync)
CryFixedStringT<1024> hlslPath;
// 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);
gEnv->pFileIO->CreatePath(shaderSourceOutputFolder);
diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/D3DSystem.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/D3DSystem.cpp
index 7f9274da86..7fa44a8983 100644
--- a/Code/CryEngine/RenderDll/XRenderD3D9/D3DSystem.cpp
+++ b/Code/CryEngine/RenderDll/XRenderD3D9/D3DSystem.cpp
@@ -70,6 +70,7 @@
#endif
#include "../Common/RenderCapabilities.h"
+#include
#ifdef WIN32
// 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 ("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);
diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
index 2ff07d9147..0b783239c7 100644
--- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
+++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
@@ -20,6 +20,8 @@
#include
#include
+#include
+
#include
#include
@@ -99,6 +101,18 @@ namespace AZ
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
// [5/30/2012]
@@ -159,6 +173,80 @@ namespace AZ
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)app;
@@ -276,6 +364,7 @@ namespace AZ
}
ComponentApplication::ComponentApplication(int argC, char** argV)
+ : m_eventLogger{}
{
if (argV)
{
@@ -284,11 +373,23 @@ namespace AZ
}
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
// 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::Get() == nullptr)
+ {
+ m_eventLogger.reset(new AZ::Debug::LocalFileEventLogger);
+ }
+ else
+ {
+ m_eventLogger = EventLoggerPtr(static_cast(AZ::Interface::Get()),
+ EventLoggerDeleter{ true });
}
// 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
m_commandLine.Parse(m_argC, m_argV);
+ ParseCommandLine(m_commandLine);
// 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
@@ -304,62 +406,34 @@ namespace AZ
m_settingsRegistry = AZStd::make_unique();
// 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());
}
// 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
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.
SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(*m_settingsRegistry);
- constexpr bool executeRegDumpCommands = false;
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*m_settingsRegistry);
@@ -391,11 +465,11 @@ namespace AZ
Destroy();
}
- // The m_gameProjectChangedHandler stores an AZStd::function internally
+ // The m_projectChangedHandler stores an AZStd::function internally
// 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
- m_gameProjectChangedHandler = {};
+ m_projectChangedHandler = {};
// Delete the AZ::IConsole if it was created by this application instance
if (m_ownsConsole)
@@ -412,6 +486,10 @@ namespace AZ
}
m_settingsRegistry.reset();
+ // Set AZ::CommandLine to an empty object to clear out allocated memory before the allocators
+ // are destroyed
+ m_commandLine = {};
+
DestroyAllocator();
}
@@ -421,17 +499,6 @@ namespace AZ
AZ_Assert(!m_isStarted, "Component application already started!");
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;
@@ -461,20 +528,14 @@ namespace AZ
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";
- registryValue.clear();
-
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();
@@ -515,7 +576,9 @@ namespace AZ
LoadModules();
// 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
m_console->ExecuteCommandLine(m_commandLine);
@@ -601,7 +664,7 @@ namespace AZ
m_drillerManager = nullptr;
}
- m_eventLogger.Stop();
+ m_eventLogger->Stop();
// Clear the descriptor to deallocate all strings (owned by ModuleDescriptor)
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 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)
{
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
// 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.
- 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);
#endif
SettingsRegistryMergeUtils::MergeSettingsToRegistry_EngineRegistry(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);
#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);
#endif
}
@@ -1013,7 +1116,7 @@ namespace AZ
struct GemModuleLoadData
{
AZ::OSString m_gemName;
- AZ::OSString m_dynamicLibraryPath;
+ AZStd::vector m_dynamicLibraryPaths;
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 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)
{
- 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::format("%s/Gems", AZ::SettingsRegistryMergeUtils::OrganizationRootKey);
+ auto gemModuleKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/Gems", AZ::SettingsRegistryMergeUtils::OrganizationRootKey);
ModuleDescriptorList gemModules;
{
GemModuleVisitor moduleVisitor;
- m_settingsRegistry->Visit(moduleVisitor, gemModuleKey);
+ m_settingsRegistry->Visit(moduleVisitor, gemModuleKey);
for (GemModuleLoadData& moduleLoadData : moduleVisitor.m_modulesLoadData)
{
// 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
for (auto&& moduleDescriptor : m_descriptor.m_modules)
{
// Append new dynamic library modules to the descriptor array
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);
foundModuleIter == gemModules.end())
@@ -1260,17 +1373,8 @@ namespace AZ
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 appRootPath = Utils::GetDefaultAppRootPath(); appRootPath)
{
m_appRoot = AZStd::move(*appRootPath);
@@ -1279,26 +1383,14 @@ namespace AZ
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)
diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h
index e43f1f9938..4d1e26d242 100644
--- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h
+++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h
@@ -9,15 +9,13 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
-#ifndef AZCORE_COMPONENT_APPLICATION_H
-#define AZCORE_COMPONENT_APPLICATION_H
+#pragma once
#include
#include
#include
#include
#include
-#include
#include
#include
#include
@@ -40,12 +38,15 @@ namespace AZ
class IConsole;
class Module;
class ModuleManager;
+}
+namespace AZ::Debug
+{
+ class DrillerManager;
+ class LocalFileEventLogger;
+}
- namespace Debug
- {
- class DrillerManager;
- }
-
+namespace AZ
+{
class ReflectionEnvironment
{
public:
@@ -167,15 +168,6 @@ namespace AZ
//! \note Dynamic AZ::Modules are specified in the ComponentApplication::Descriptor.
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//pc
- const char* m_cacheRootPath = nullptr;
-
- //! The path to the project in the asset cache folder. For instance: ./cache//pc/
- 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.
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.
/// It's expected that derived applications will implement an application root.
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.
const char* GetExecutableFolder() const override { return m_exeDirectory.c_str(); }
@@ -331,6 +325,9 @@ namespace AZ
/// Create the drillers
void CreateDrillers();
+ /// Parse ComponentApplication specific command line arguments
+ void ParseCommandLine(const AZ::CommandLine& commandLine);
+
virtual void MergeSettingsToRegistry(SettingsRegistryInterface& registry);
//! 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.
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
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.
IAllocatorAllocate* m_osAllocator{ nullptr };
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
// 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
// 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.
- 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;
+ EventLoggerPtr m_eventLogger;
};
}
-
-#endif // AZCORE_COMPONENT_APPLICATION_H
-#pragma once
diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplicationBus.h b/Code/Framework/AzCore/AzCore/Component/ComponentApplicationBus.h
index 993646358d..96aa56bfea 100644
--- a/Code/Framework/AzCore/AzCore/Component/ComponentApplicationBus.h
+++ b/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.
*/
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.
* @return A pointer to the name of the path that contains the application's executable.
diff --git a/Code/Framework/AzCore/AzCore/Console/Console.cpp b/Code/Framework/AzCore/AzCore/Console/Console.cpp
index 7623eb3f5f..3701f35f8d 100644
--- a/Code/Framework/AzCore/AzCore/Console/Console.cpp
+++ b/Code/Framework/AzCore/AzCore/Console/Console.cpp
@@ -161,9 +161,11 @@ namespace AZ
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);
}
}
diff --git a/Code/Framework/AzCore/AzCore/IO/FileIO.h b/Code/Framework/AzCore/AzCore/IO/FileIO.h
index c69d8304e9..d253d6dae5 100644
--- a/Code/Framework/AzCore/AzCore/IO/FileIO.h
+++ b/Code/Framework/AzCore/AzCore/IO/FileIO.h
@@ -67,25 +67,7 @@ namespace AZ
return a != OpenMode::Invalid;
}
- inline OpenMode operator | (OpenMode a, OpenMode b)
- {
- return static_cast(static_cast(a) | static_cast(b));
- }
-
- inline OpenMode operator & (OpenMode a, OpenMode b)
- {
- return static_cast(static_cast(a) & static_cast(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);
@@ -250,12 +232,14 @@ namespace AZ
virtual bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const = 0;
AZStd::optional 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;
//! 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;
AZStd::optional 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.
virtual bool GetFilename(HandleType fileHandle, char* filename, AZ::u64 filenameSize) const = 0;
diff --git a/Code/Framework/AzCore/AzCore/IO/Path/Path.h b/Code/Framework/AzCore/AzCore/IO/Path/Path.h
index b25b1b6fe1..97f528d1dc 100644
--- a/Code/Framework/AzCore/AzCore/IO/Path/Path.h
+++ b/Code/Framework/AzCore/AzCore/IO/Path/Path.h
@@ -170,7 +170,7 @@ namespace AZ::IO
//! Check whether the path is not absolute
[[nodiscard]] constexpr bool IsRelative() const;
//! 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.
//! # Path separators are converted to their preferred path separator
@@ -517,7 +517,7 @@ namespace AZ::IO
//! Checks if the path has a root directory
[[nodiscard]] constexpr bool HasRootDirectory() const;
//! 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;
//! checks whether the relative part of path is empty
//! (C:\\ lumberyard\dev\)
@@ -539,8 +539,8 @@ namespace AZ::IO
[[nodiscard]] constexpr bool IsAbsolute() const;
//! Check whether the path is not absolute
[[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
//! Given a windows path of "C:\lumberyard\foo\bar\name.txt" and a posix path of
diff --git a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl b/Code/Framework/AzCore/AzCore/IO/Path/Path.inl
index 7f90a61116..576ff215c9 100644
--- a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl
+++ b/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
for(--pathParserEnd, --patternParserEnd; pathParserEnd && patternParserEnd; --pathParserEnd, --patternParserEnd)
{
- if (!AZStd::wildcard_match(*patternParserEnd, *pathParserEnd))
+ if (!AZStd::wildcard_match_case(*patternParserEnd, *pathParserEnd))
{
return false;
}
@@ -1830,9 +1830,9 @@ namespace AZ::IO
}
template
- [[nodiscard]] constexpr bool BasicPath::IsRelativeTo() const
+ [[nodiscard]] constexpr bool BasicPath::IsRelativeTo(const PathView& base) const
{
- return static_cast(*this).IsRelative();
+ return static_cast(*this).IsRelativeTo(base);
}
template
diff --git a/Code/Framework/AzCore/AzCore/Math/MathReflection.cpp b/Code/Framework/AzCore/AzCore/Math/MathReflection.cpp
index c90677d6f3..06bc5de92a 100644
--- a/Code/Framework/AzCore/AzCore/Math/MathReflection.cpp
+++ b/Code/Framework/AzCore/AzCore/Math/MathReflection.cpp
@@ -369,6 +369,7 @@ namespace AZ
context.Serializer()->HandlesType();
context.Serializer()->HandlesType();
context.Serializer()->HandlesType();
+ context.Serializer()->HandlesType();
}
void MathReflect(ReflectContext* context)
diff --git a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp
index ac3d663164..aa9686f709 100644
--- a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp
@@ -14,6 +14,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -238,4 +239,56 @@ namespace AZ
{
return JsonMathVectorSerializerInternal::Store(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(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());
+ 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(), itr->value, context);
+ if (intermediate.GetResultCode().GetProcessing() != JSR::Processing::Completed)
+ {
+ return intermediate;
+ }
+ }
+
+ auto eulerAnglesDegrees = Vector3::CreateFromFloat3(values);
+ reinterpret_cast(outputValue)->SetFromEulerDegrees(eulerAnglesDegrees);
+ return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success, "Successfully read quaternion.");
+ }
+
+ return JsonMathVectorSerializerInternal::Load(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(outputValue, inputValue, defaultValue, valueTypeId, context);
+ }
}
diff --git a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.h b/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.h
index 9c401d2aff..9c2606b932 100644
--- a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.h
+++ b/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,
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;
+ };
}
diff --git a/Code/Framework/AzCore/AzCore/Settings/CommandLine.cpp b/Code/Framework/AzCore/AzCore/Settings/CommandLine.cpp
index c7a5476340..6549992dc0 100644
--- a/Code/Framework/AzCore/AzCore/Settings/CommandLine.cpp
+++ b/Code/Framework/AzCore/AzCore/Settings/CommandLine.cpp
@@ -10,11 +10,11 @@
*
*/
-#include
+#include
+#include
#include
+#include
#include
-#include
-#include
namespace AZ
{
@@ -29,6 +29,21 @@ namespace AZ
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(arg.size()), arg.data()) : AZStd::string{ arg };
+ }
}
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 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 (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);
if (currentArg[0] == '-') // for -- extra
@@ -57,93 +119,41 @@ namespace AZ
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)
{
- // 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 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
- // 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();
}
else
{
- // its in this format /switchName switchvalue
+ // its in this format -switchName switchvalue
// (no equals)
- currentSwitch = currentArg;
- currentSwitch = ToLower(currentSwitch);
- m_switches.insert_key(currentSwitch);
+ currentSwitch = ToLower(currentArg);
+ m_allValues.push_back({ currentSwitch, "" });
}
}
else
{
if (currentSwitch.empty())
{
- m_miscValues.push_back(currentArg);
+ m_allValues.push_back({ "", UnquoteArgument(currentArg) });
}
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 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)
{
- m_switches.clear();
- m_miscValues.clear();
+ m_allValues.clear();
AZStd::string currentSwitch;
// 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
{
- 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
{
- 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
{
- 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, ¤tPosIndex](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 switchFound->second.at(index);
+ return commandArgumentIter->m_value;
}
AZStd::size_t CommandLine::GetNumMiscValues() const
{
- return m_miscValues.size();
+ return GetNumSwitchValues("");
}
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();
}
}
diff --git a/Code/Framework/AzCore/AzCore/Settings/CommandLine.h b/Code/Framework/AzCore/AzCore/Settings/CommandLine.h
index 860e05f2b2..24e4571cd2 100644
--- a/Code/Framework/AzCore/AzCore/Settings/CommandLine.h
+++ b/Code/Framework/AzCore/AzCore/Settings/CommandLine.h
@@ -36,36 +36,47 @@ namespace AZ
public:
AZ_CLASS_ALLOCATOR(CommandLine, AZ::SystemAllocator, 0);
+ using ParamContainer = AZStd::vector;
+
+ struct CommandArgument
+ {
+ AZStd::string m_option;
+ AZStd::string m_value;
+ };
+ using ArgumentVector = AZStd::vector;
+
CommandLine();
/**
* Initializes a CommandLine instance which uses the provided commandLineOptionPreix for parsing switches
*/
CommandLine(AZStd::string_view commandLineOptionPrefix);
-
- using ParamContainer = AZStd::vector;
- using ParamMap = AZStd::unordered_map;
/**
* Construct a command line parser.
* 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);
+ /**
+ * 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);
/**
* 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
- * 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
* MiscValue = ["Foo", "Bat"]
* Switches = ["GameFolder" : [], "RemoteIp" : ["10.0.0.1"], "ScanFolders" : ["\a\b\c", "\d\e\f"]
* CommandLineOptionPrefix = "-/"
*
* 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
@@ -97,16 +108,28 @@ namespace AZ
*/
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:
- 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;
inline static constexpr size_t MaxCommandOptionPrefixes = 8;
diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp
index d69392889f..9ea76817af 100644
--- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp
+++ b/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.
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;
}
}
diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp
index 440d404526..f9fd606714 100644
--- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp
+++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp
@@ -41,68 +41,197 @@ namespace AZ::Internal
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 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> 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 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::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 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 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::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
// 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 {};
}
@@ -111,9 +240,9 @@ namespace AZ::SettingsRegistryMergeUtils
constexpr AZStd::string_view 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 sectionName;
- constexpr char sectionHeaderStart= '[';
+ constexpr char sectionHeaderStart = '[';
constexpr char sectionHeaderEnd = ']';
if (line.starts_with(sectionHeaderStart) && line.ends_with(sectionHeaderEnd))
{
@@ -184,7 +313,7 @@ namespace AZ::SettingsRegistryMergeUtils
void QuerySpecializationsFromRegistry(SettingsRegistryInterface& registry, SettingsRegistryInterface::Specializations& specializations)
{
- // Append any specializations stored in the registry
+ // Append any specializations stored in the registry
struct SpecializationsVisitor
: AZ::SettingsRegistryInterface::Visitor
{
@@ -222,7 +351,7 @@ namespace AZ::SettingsRegistryMergeUtils
bool MergeSettingsToRegistry_ConfigFile(SettingsRegistryInterface& registry, AZStd::string_view filePath,
const ConfigParserSettings& configParserSettings)
{
- auto configPath = GetAppRoot(®istry) / filePath;
+ auto configPath = FindEngineRoot(registry) / filePath;
IO::SystemFile configFile;
if (!configFile.Open(configPath.c_str(), IO::SystemFile::OpenMode::SF_OPEN_READ_ONLY))
{
@@ -348,9 +477,13 @@ namespace AZ::SettingsRegistryMergeUtils
ConfigParserSettings parserSettings;
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;
};
@@ -365,71 +498,104 @@ namespace AZ::SettingsRegistryMergeUtils
registry.Set(FilePathKey_BinaryFolder, path.LexicallyNormal().Native());
// Engine root folder - corresponds to the @engroot@ and @devroot@ aliases
- AZ::IO::FixedMaxPath appRoot = GetAppRoot(®istry);
- 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;
- auto buffer = AZStd::fixed_string::format("%s/sys_game_folder", BootstrapSettingsRootKey);
+ auto buffer = AZStd::fixed_string::format("%s/project_path", BootstrapSettingsRootKey);
- AZStd::string_view projectPath(buffer);
+ AZ::SettingsRegistryInterface::FixedValueString projectPathKey(buffer);
SettingsRegistryInterface::FixedValueString projectPathValue;
- if (registry.Get(projectPathValue, projectPath))
+ if (registry.Get(projectPathValue, projectPathKey))
{
// Cache folder
// 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;
SettingsRegistryInterface::FixedValueString assetPlatform;
buffer = AZStd::fixed_string::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::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()),
- 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(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 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::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
{
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(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(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,
@@ -535,7 +701,7 @@ namespace AZ::SettingsRegistryMergeUtils
const SettingsRegistryInterface::Specializations& specializations, AZStd::vector* scratchBuffer)
{
AZ::SettingsRegistryInterface::FixedValueString sourceGamePath;
- if (registry.Get(sourceGamePath, FilePathKey_SourceGameFolder))
+ if (registry.Get(sourceGamePath, FilePathKey_ProjectPath))
{
AZ::IO::FixedMaxPath mergePath{ sourceGamePath };
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* scratchBuffer)
{
// Unlike other paths, the path can't be overwritten by the dev settings because that would create a circular dependency.
- auto mergePath = GetAppRoot(®istry);
- 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)
{
- 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(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);
}
- 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(regdumpallValue.size()), regdumpallValue.data());
- }
-
DumperSettings dumperSettings{ prettifyOutput };
AZ::IO::StdoutStream outputStream;
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
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(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,
@@ -649,38 +831,21 @@ namespace AZ::SettingsRegistryMergeUtils
struct SettingsExportVisitor
: SettingsRegistryInterface::Visitor
{
- using SettingsWriter = AZStd::variant<
- rapidjson::PrettyWriter,
- rapidjson::Writer>;
- SettingsWriter m_writer;
- AZ::IO::RapidJSONStreamWriter m_rapidJsonStream;
- DumperSettings m_dumperSettings;
- AZStd::stack m_includeNameStack;
- bool m_includeName{};
- bool m_result{ true };
-
SettingsExportVisitor(AZ::IO::GenericStream& stream, const DumperSettings& dumperSettings)
: m_rapidJsonStream{ &stream }
, m_dumperSettings{ dumperSettings }
+ , m_writer{ m_stringBuffer }
{
- if (m_dumperSettings.m_prettifyOutput)
- {
- m_writer.emplace>(m_rapidJsonStream);
- }
- else
- {
- m_writer.emplace>(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(
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)
{
- 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)
{
- 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
{
- 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)
{
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
{
- 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.");
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 ?
@@ -757,42 +905,27 @@ namespace AZ::SettingsRegistryMergeUtils
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)
{
- 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)
{
- 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()
@@ -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.");
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 m_writer;
+
+ AZ::IO::RapidJSONStreamWriter m_rapidJsonStream;
+ DumperSettings m_dumperSettings;
+ AZStd::stack m_includeNameStack;
+ bool m_result{ true };
};
SettingsExportVisitor visitor(stream, dumperSettings);
diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h
index 60dd6be4bf..b86df27b36 100644
--- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h
+++ b/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 FilePathKey_BinaryFolder[] = "/Amazon/AzCore/Runtime/FilePaths/BinaryFolder";
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. /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. /Cache/
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
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";
- //! 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
- //! 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.
//! 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,
const SettingsRegistryInterface::Specializations& specializations, AZStd::vector* 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.
- 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* scratchBuffer = nullptr);
//! 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 Sets a value in the registry. See MergeCommandLineArgument for options for
//! example: --regset "/My/String/Value=String value set"
+ //! --regremove Removes a value in the registry
+ //! example: --regremove "/My/String/Value"
+ //! only when executeCommands is true are the following options supported:
//! --regdump Dumps the content of the key at path and all it's content/children to output.
//! example: --regdump /My/Array/With/Objects
//! --regdumpall Dumps the entire settings registry to output.
@@ -169,7 +189,11 @@ namespace AZ::SettingsRegistryMergeUtils
//! Stores the command line settings into the Setting Registry
//! 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
struct DumperSettings
@@ -179,14 +203,25 @@ namespace AZ::SettingsRegistryMergeUtils
//! Include filter which is used to indicate which paths of the Settings Registry
//! should be traversed.
//! 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 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":{ }
+ //! }
+ //! }
+ AZStd::string_view m_jsonPointerPrefix;
};
//! 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,
AZ::IO::GenericStream& stream, const DumperSettings& dumperSettings);
diff --git a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp
index bb911f2684..096c1282db 100644
--- a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp
+++ b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp
@@ -418,36 +418,37 @@ namespace AZ::StringFunc::Internal
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*/)
{
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)
{
@@ -496,9 +505,18 @@ namespace AZ
&& 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;
}
@@ -508,7 +526,7 @@ namespace AZ
pos = 0;
}
- size_t inLen = strlen(in);
+ size_t inLen = in.size();
if (inLen < pos)
{
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*/)
{
- 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;
}
@@ -773,7 +797,7 @@ namespace AZ
bool bIsSpaces = false;
if (!bIsEmpty)
{
- AZStd::string_view strippedNextToken = Internal::StripEnds(*nextToken, " ");
+ AZStd::string_view strippedNextToken = StripEnds(*nextToken, " ");
bIsSpaces = strippedNextToken.empty();
}
@@ -805,7 +829,7 @@ namespace AZ
bool bIsSpaces = false;
if (!bIsEmpty)
{
- AZStd::string_view strippedNextToken = Internal::StripEnds(*nextToken, " ");
+ AZStd::string_view strippedNextToken = StripEnds(*nextToken, " ");
bIsSpaces = strippedNextToken.empty();
}
diff --git a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h
index aa21057890..7dc4b79090 100644
--- a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h
+++ b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h
@@ -12,6 +12,7 @@
#pragma once
+#include
#include
#include
#include
@@ -107,6 +108,22 @@ namespace AZ
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(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 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
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);
//! First and Last Character
@@ -196,6 +213,33 @@ namespace AZ
*/
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 away the leading, trailing or all character(s) or substring(s) in a AZStd::string with
*! case sensitivity.
@@ -669,8 +713,7 @@ namespace AZ
*/
namespace Path
{
- inline constexpr size_t MaxPathLength = 1024;
- using FixedString = AZStd::fixed_string;
+ using FixedString = AZ::IO::FixedMaxPathString;
//! Normalize
/*! Normalizes a path and returns returns StringFunc::Path::IsValid()
*! strips all AZ_FILESYSTEM_INVALID_CHARACTERS
@@ -791,7 +834,7 @@ namespace AZ
//! StripFullName
/*! 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);
diff --git a/Code/Framework/AzCore/AzCore/UnitTest/MockComponentApplication.h b/Code/Framework/AzCore/AzCore/UnitTest/MockComponentApplication.h
index d9fd5067ce..309618e196 100644
--- a/Code/Framework/AzCore/AzCore/UnitTest/MockComponentApplication.h
+++ b/Code/Framework/AzCore/AzCore/UnitTest/MockComponentApplication.h
@@ -39,6 +39,7 @@ namespace UnitTest
MOCK_METHOD0(GetJsonRegistrationContext, AZ::JsonRegistrationContext* ());
MOCK_METHOD0(GetBehaviorContext, AZ::BehaviorContext* ());
MOCK_CONST_METHOD0(GetAppRoot, const char* ());
+ MOCK_CONST_METHOD0(GetEngineRoot, const char* ());
MOCK_CONST_METHOD0(GetExecutableFolder, const char* ());
MOCK_METHOD0(GetDrillerManager, AZ::Debug::DrillerManager* ());
MOCK_CONST_METHOD1(QueryApplicationType, void(AZ::ApplicationTypeQuery&));
diff --git a/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockFileIOBase.h b/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockFileIOBase.h
index 96be703e8a..a9466fd765 100644
--- a/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockFileIOBase.h
+++ b/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_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(ReplaceAlias, bool(AZ::IO::FixedMaxPath& replacedAliasPath, const AZ::IO::PathView& path));
MOCK_CONST_METHOD3(GetFilename, bool(HandleType fileHandle, char* filename, AZ::u64 filenameSize));
using FileIOBase::ConvertToAlias;
using FileIOBase::ResolvePath;
diff --git a/Code/Framework/AzCore/AzCore/Utils/Utils.cpp b/Code/Framework/AzCore/AzCore/Utils/Utils.cpp
index c9c20173db..e20d36b12f 100644
--- a/Code/Framework/AzCore/AzCore/Utils/Utils.cpp
+++ b/Code/Framework/AzCore/AzCore/Utils/Utils.cpp
@@ -16,6 +16,8 @@
#include
#include
#include
+#include
+#include
#include
namespace AZ::Utils
@@ -40,6 +42,47 @@ namespace AZ::Utils
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 WriteFile(AZStd::string_view content, AZStd::string_view filePath)
{
AZ::IO::FixedMaxPath filePathFixed = filePath; // Because FileIOStream requires a null-terminated string
diff --git a/Code/Framework/AzCore/AzCore/Utils/Utils.h b/Code/Framework/AzCore/AzCore/Utils/Utils.h
index 9334c0d61f..431bf7487a 100644
--- a/Code/Framework/AzCore/AzCore/Utils/Utils.h
+++ b/Code/Framework/AzCore/AzCore/Utils/Utils.h
@@ -16,6 +16,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -24,9 +26,6 @@ namespace AZ
{
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.
//! 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;
@@ -77,10 +76,22 @@ namespace AZ
//! @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);
+ //! 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. "/.o3de/o3de_manifest.json"
+ AZ::IO::FixedMaxPathString GetEngineManifestPath();
+
//! Retrieves the App root path to use on the current platform
//! If the optional is not engaged the AppRootPath should be calculated based
//! on the location of the bootstrap.cfg file
- AZStd::optional> GetDefaultAppRootPath();
+ AZStd::optional