diff --git a/Assets/Editor/MapScreenshotSettings.xml b/Assets/Editor/MapScreenshotSettings.xml
index 01f90db4b3..88a8a49aef 100644
--- a/Assets/Editor/MapScreenshotSettings.xml
+++ b/Assets/Editor/MapScreenshotSettings.xml
@@ -1,18 +1,5 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Assets/Editor/UserTools.xml b/Assets/Editor/UserTools.xml
index 8f971cbd5c..4cc197afbe 100644
--- a/Assets/Editor/UserTools.xml
+++ b/Assets/Editor/UserTools.xml
@@ -7,8 +7,6 @@
-
-
diff --git a/Assets/Engine/Config/AutoTestChain.cfg b/Assets/Engine/Config/AutoTestChain.cfg
index 8c6fae9020..4164acb271 100644
--- a/Assets/Engine/Config/AutoTestChain.cfg
+++ b/Assets/Engine/Config/AutoTestChain.cfg
@@ -1,16 +1,5 @@
ConsoleHide
-g_godMode=1
sys_warnings=0
con_showonload=1
-i_forcefeedback=0
-g_infiniteammo=1
-e_ObjectLayersActivation=0
-e_ObjectLayersActivationPhysics=0
-g_flashrenderingduringloading=0
sys_maxfps=0
r_vsync=0
-p_max_substeps=1
-demo_file=autotest
-demo_num_runs=0
-demo_quit=1
-demo_ai=1
diff --git a/Assets/Engine/Config/AutoTestTimeDemo.cfg b/Assets/Engine/Config/AutoTestTimeDemo.cfg
index 687158eda9..664ea94939 100644
--- a/Assets/Engine/Config/AutoTestTimeDemo.cfg
+++ b/Assets/Engine/Config/AutoTestTimeDemo.cfg
@@ -1,15 +1,5 @@
ConsoleHide
-g_godMode=1
-g_infiniteammo=1
r_displayinfo=1
s_profiling=1
sys_maxfps=0
-e_ObjectLayersActivation=0
-e_ObjectLayersActivationPhysics=0
-
-demo_file=autotest
-demo_num_runs=2
-demo_quit=1
-demo_savestats=1
-demo_profile=-1
demo
diff --git a/Assets/Engine/Config/AutotestPlaythrough.cfg b/Assets/Engine/Config/AutotestPlaythrough.cfg
index f453097972..664ea94939 100644
--- a/Assets/Engine/Config/AutotestPlaythrough.cfg
+++ b/Assets/Engine/Config/AutotestPlaythrough.cfg
@@ -1,12 +1,5 @@
ConsoleHide
-g_godMode=1
-g_infiniteammo=1
r_displayinfo=1
s_profiling=1
sys_maxfps=0
-demo_file=playthru
-demo_num_runs=2
-demo_quit=1
-demo_savestats=1
-demo_profile=-1
-demo
\ No newline at end of file
+demo
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Full.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Full.cfg
index 626dce3ee4..04fb56f3ca 100644
--- a/Assets/Engine/Config/CVarGroups/sys_spec_Full.cfg
+++ b/Assets/Engine/Config/CVarGroups/sys_spec_Full.cfg
@@ -11,113 +11,16 @@
; default of this CVarGroup
= 7
-sys_spec_ObjectDetail=7
-sys_spec_Shading=7
-sys_spec_VolumetricEffects=7
-sys_spec_Shadows=7
-sys_spec_Texture=7
-sys_spec_Physics=7
-sys_spec_PostProcessing=7
-sys_spec_Particles=7
-sys_spec_Sound=7
-sys_spec_Water=7
-sys_spec_GameEffects=7
-sys_spec_light=7
-
[1]
-sys_spec_ObjectDetail=1
-sys_spec_Shading=1
-sys_spec_VolumetricEffects=1
-sys_spec_Shadows=1
-sys_spec_Texture=1
-sys_spec_Physics=1
-sys_spec_PostProcessing=1
-sys_spec_Particles=1
-sys_spec_Sound=1
-sys_spec_Water=1
-sys_spec_GameEffects=1
-sys_spec_light=1
[2]
-sys_spec_ObjectDetail=2
-sys_spec_Shading=2
-sys_spec_VolumetricEffects=2
-sys_spec_Shadows=2
-sys_spec_Texture=2
-sys_spec_Physics=2
-sys_spec_PostProcessing=2
-sys_spec_Particles=2
-sys_spec_Sound=2
-sys_spec_Water=2
-sys_spec_GameEffects=2
-sys_spec_light=2
[3]
-sys_spec_ObjectDetail=3
-sys_spec_Shading=3
-sys_spec_VolumetricEffects=3
-sys_spec_Shadows=3
-sys_spec_Texture=3
-sys_spec_Physics=3
-sys_spec_PostProcessing=3
-sys_spec_Particles=3
-sys_spec_Sound=3
-sys_spec_Water=3
-sys_spec_GameEffects=3
-sys_spec_light=3
[4]
-sys_spec_ObjectDetail=4
-sys_spec_Shading=4
-sys_spec_VolumetricEffects=4
-sys_spec_Shadows=4
-sys_spec_Texture=4
-sys_spec_Physics=4
-sys_spec_PostProcessing=4
-sys_spec_Particles=4
-sys_spec_Sound=4
-sys_spec_Water=4
-sys_spec_GameEffects=4
-sys_spec_light=4
[5]
-sys_spec_ObjectDetail=5
-sys_spec_Shading=5
-sys_spec_VolumetricEffects=5
-sys_spec_Shadows=5
-sys_spec_Texture=5
-sys_spec_Physics=5
-sys_spec_PostProcessing=5
-sys_spec_Particles=5
-sys_spec_Sound=5
-sys_spec_Water=5
-sys_spec_GameEffects=5
-sys_spec_light=5
[6]
-sys_spec_ObjectDetail=6
-sys_spec_Shading=6
-sys_spec_VolumetricEffects=6
-sys_spec_Shadows=6
-sys_spec_Texture=6
-sys_spec_Physics=6
-sys_spec_PostProcessing=6
-sys_spec_Particles=6
-sys_spec_Sound=6
-sys_spec_Water=6
-sys_spec_GameEffects=6
-sys_spec_light=6
[8]
-sys_spec_ObjectDetail=8
-sys_spec_Shading=8
-sys_spec_VolumetricEffects=8
-sys_spec_Shadows=8
-sys_spec_Texture=8
-sys_spec_Physics=8
-sys_spec_PostProcessing=8
-sys_spec_Particles=8
-sys_spec_Sound=8
-sys_spec_Water=8
-sys_spec_GameEffects=8
-sys_spec_light=8
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_GameEffects.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_GameEffects.cfg
deleted file mode 100644
index 34e058d47d..0000000000
--- a/Assets/Engine/Config/CVarGroups/sys_spec_GameEffects.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-[default]
-; default of this CVarGroup
-= 7
-
-mfx_Timeout = 0.01
-
-
-
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_ObjectDetail.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_ObjectDetail.cfg
deleted file mode 100644
index a2996f7ded..0000000000
--- a/Assets/Engine/Config/CVarGroups/sys_spec_ObjectDetail.cfg
+++ /dev/null
@@ -1,160 +0,0 @@
-[default]
-; default of this CVarGroup
-= 7
-
-ca_AttachmentCullingRation=360
-es_DebrisLifetimeScale=1
-e_CoverageBufferReproj=6
-e_DecalsAllowGameDecals=1
-e_DecalsLifeTimeScale=2
-e_DecalsOverlapping=1
-e_Dissolve=2
-e_LightQuality=3
-e_LodMin=0
-e_LodRatio=20
-e_MaxViewDistSpecLerp=1
-e_MergedMeshesInstanceDist=1.0
-e_MergedMeshesPool=8192
-e_ObjQuality=3
-e_OcclusionCullingViewDistRatio=1
-e_ProcVegetation=1
-e_StatObjBufferRenderTasks=1
-e_StreamCgf=0
-e_TerrainLodRatio=1
-e_TerrainOcclusionCullingMaxDist=200
-e_Tessellation=0
-e_VegetationMinSize=0
-e_ViewDistMin=10
-e_ViewDistRatio=100
-e_ViewDistRatioCustom=100
-e_ViewDistRatioDetail=100
-e_ViewDistRatioLights=50
-e_ViewDistRatioVegetation=100
-r_DrawNearZRange=0.12
-r_FlaresTessellationRatio=1
-r_SilhouettePOM=0
-r_usezpass=2
-
-[1]
-ca_AttachmentCullingRation=145
-es_DebrisLifetimeScale=0.6
-e_DecalsLifeTimeScale=1
-e_Dissolve=0
-e_LightQuality=1
-e_LodRatio=10
-e_MaxViewDistSpecLerp=0.5
-e_ObjQuality=1
-e_TerrainOcclusionCullingMaxDist=130
-e_VegetationMinSize=0.5
-e_ViewDistRatioCustom=60
-e_ViewDistRatioDetail=25
-e_ViewDistRatioLights=25
-e_ViewDistRatioVegetation=21
-r_FlaresTessellationRatio=0.25
-r_usezpass=1
-e_ProcVegetation=0
-e_ViewDistRatio=50
-
-[2]
-ca_AttachmentCullingRation=145
-es_DebrisLifetimeScale=0.6
-e_DecalsLifeTimeScale=1
-e_Dissolve=0
-e_LightQuality=2
-e_LodRatio=10
-e_MaxViewDistSpecLerp=0.5
-e_ObjQuality=2
-e_TerrainOcclusionCullingMaxDist=130
-e_VegetationMinSize=0.5
-e_ViewDistRatioCustom=60
-e_ViewDistRatioDetail=25
-e_ViewDistRatioLights=25
-e_ViewDistRatioVegetation=50
-r_FlaresTessellationRatio=0.25
-r_usezpass=1
-e_ProcVegetation=1
-e_ViewDistRatio=50
-
-[3]
-ca_AttachmentCullingRation=145
-es_DebrisLifetimeScale=0.6
-e_DecalsLifeTimeScale=1
-e_Dissolve=0
-e_LightQuality=3
-e_LodRatio=10
-e_MaxViewDistSpecLerp=0.5
-e_ObjQuality=3
-e_TerrainOcclusionCullingMaxDist=130
-e_VegetationMinSize=0.5
-e_ViewDistRatioCustom=60
-e_ViewDistRatioDetail=25
-e_ViewDistRatioLights=25
-e_ViewDistRatioVegetation=50
-r_FlaresTessellationRatio=0.25
-r_usezpass=1
-e_ProcVegetation=1
-e_ViewDistRatio=75
-
-[4]
-ca_AttachmentCullingRation=145
-es_DebrisLifetimeScale=0.6
-e_DecalsLifeTimeScale=1
-e_Dissolve=0
-e_LightQuality=4
-e_LodRatio=10
-e_MaxViewDistSpecLerp=0.5
-e_ObjQuality=4
-e_TerrainOcclusionCullingMaxDist=130
-e_VegetationMinSize=0.5
-e_ViewDistRatioCustom=60
-e_ViewDistRatioDetail=25
-e_ViewDistRatioLights=25
-e_ViewDistRatioVegetation=50
-r_FlaresTessellationRatio=0.25
-r_usezpass=1
-e_ProcVegetation=1
-e_ViewDistRatio=75
-
-[5]
-ca_AttachmentCullingRation=145
-es_DebrisLifetimeScale=0.6
-e_DecalsLifeTimeScale=1
-e_LightQuality=1
-e_LodRatio=10
-e_MaxViewDistSpecLerp=0.5
-e_ObjQuality=1
-e_TerrainOcclusionCullingMaxDist=130
-e_VegetationMinSize=0.5
-e_ViewDistRatio=50
-e_ViewDistRatioCustom=60
-e_ViewDistRatioDetail=25
-e_ViewDistRatioLights=25
-e_ViewDistRatioVegetation=50
-r_FlaresTessellationRatio=0.25
-
-[6]
-ca_AttachmentCullingRation=300
-es_DebrisLifetimeScale=0.8
-e_LightQuality=2
-e_LodRatio=15
-e_ObjQuality=2
-e_ViewDistRatio=75
-e_ViewDistRatioDetail=35
-e_ViewDistRatioVegetation=75
-
-[8]
-ca_AttachmentCullingRation=400
-e_LightQuality=4
-e_LodRatio=40
-e_MergedMeshesInstanceDist=2.0
-e_MergedMeshesPool=16384
-e_ObjQuality=4
-e_TerrainLodRatio=0.5
-e_Tessellation=1
-e_ViewDistRatio=125
-e_ViewDistRatioCustom=125
-e_ViewDistRatioDetail=125
-e_ViewDistRatioLights=75
-e_ViewDistRatioVegetation=125
-r_DrawNearZRange = 0.08
-r_SilhouettePOM=1
\ No newline at end of file
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Particles.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Particles.cfg
deleted file mode 100644
index 0a02170b97..0000000000
--- a/Assets/Engine/Config/CVarGroups/sys_spec_Particles.cfg
+++ /dev/null
@@ -1,94 +0,0 @@
-[default]
-; default of this CVarGroup
-= 7
-
-e_ParticlesGI=1
-e_ParticlesPreload=0
-e_ParticlesMaxScreenFill=128
-e_ParticlesMinDrawPixels=1
-e_ParticlesMotionBlur=0
-e_ParticlesObjectCollisions=2
-e_ParticlesQuality=3
-e_ParticlesSortQuality=0
-e_ParticlesPoolSize=16384
-r_ParticlesHalfRes=0
-r_ParticlesTessellation=1
-r_ParticlesInstanceVertices=1
-r_ParticlesGpuMaxEmitCount=10000
-
-[1]
-e_ParticlesGI=0
-e_ParticlesPreload=1
-e_ParticlesMaxScreenFill=16
-e_ParticlesMinDrawPixels=2
-e_ParticlesObjectCollisions=1
-e_ParticlesQuality=2
-e_ParticlesPoolSize=4096
-r_ParticlesHalfRes=1
-r_ParticlesTessellation=0
-r_ParticlesInstanceVertices=0
-r_ParticlesGpuMaxEmitCount=10
-
-
-[2]
-e_ParticlesGI=0
-e_ParticlesPreload=1
-e_ParticlesMaxScreenFill=16
-e_ParticlesMinDrawPixels=2
-e_ParticlesObjectCollisions=1
-e_ParticlesQuality=2
-e_ParticlesPoolSize=4096
-r_ParticlesHalfRes=1
-r_ParticlesTessellation=0
-r_ParticlesInstanceVertices=0
-r_ParticlesGpuMaxEmitCount=100
-
-
-[3]
-e_ParticlesGI=0
-e_ParticlesPreload=1
-e_ParticlesMaxScreenFill=16
-e_ParticlesMinDrawPixels=2
-e_ParticlesObjectCollisions=1
-e_ParticlesQuality=2
-e_ParticlesPoolSize=4096
-r_ParticlesHalfRes=1
-r_ParticlesTessellation=0
-r_ParticlesInstanceVertices=0
-r_ParticlesGpuMaxEmitCount=500
-
-
-[4]
-e_ParticlesGI=0
-e_ParticlesPreload=1
-e_ParticlesMaxScreenFill=16
-e_ParticlesMinDrawPixels=2
-e_ParticlesObjectCollisions=1
-e_ParticlesQuality=2
-e_ParticlesPoolSize=4096
-r_ParticlesHalfRes=1
-r_ParticlesTessellation=0
-r_ParticlesInstanceVertices=0
-r_ParticlesGpuMaxEmitCount=1000
-
-
-[5]
-e_ParticlesMaxScreenFill=32
-e_ParticlesMinDrawPixels=1.5
-e_ParticlesObjectCollisions=1
-e_ParticlesQuality=1
-r_ParticlesHalfRes=1
-r_ParticlesTessellation=0
-r_ParticlesGpuMaxEmitCount=3000
-
-[6]
-e_ParticlesMaxScreenFill=64
-e_ParticlesObjectCollisions=1
-e_ParticlesQuality=2
-r_ParticlesGpuMaxEmitCount=5000
-
-[8]
-e_ParticlesMaxScreenFill=160
-e_ParticlesMotionBlur=1
-e_ParticlesQuality=4
-r_ParticlesGpuMaxEmitCount=1048576
\ No newline at end of file
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Physics.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Physics.cfg
deleted file mode 100644
index 15d9fc61e3..0000000000
--- a/Assets/Engine/Config/CVarGroups/sys_spec_Physics.cfg
+++ /dev/null
@@ -1,100 +0,0 @@
-[default]
-; default of this CVarGroup
-= 7
-
-es_MaxPhysDist=100
-es_MaxPhysDistInvisible=25
-e_CullVegActivation=50
-e_FoliageWindActivationDist=25
-e_PhysMinCellSize=4
-e_PhysOceanCell=0.5
-e_PhysProxyTriLimit=10000
-g_breakage_mem_limit=0
-g_breakage_particles_limit=160
-g_no_secondary_breaking=0
-g_tree_cut_reuse_dist=0
-p_gravity_z=-13
-p_max_entity_cells=300000
-p_max_MC_iters=6000
-p_max_object_splashes=3
-p_max_substeps=5
-p_max_substeps_large_group=5
-p_num_bodies_large_group=100
-p_splash_dist0=7
-p_splash_dist1=30
-p_splash_force0=10
-p_splash_force1=100
-p_splash_vel0=4.5
-p_splash_vel1=10
-v_vehicle_quality=4
-
-[1]
-es_MaxPhysDistInvisible=15
-e_CullVegActivation=30
-e_FoliageWindActivationDist=10
-e_PhysMinCellSize=16
-e_PhysOceanCell=1
-g_breakage_mem_limit=2000
-g_breakage_particles_limit=40
-g_no_secondary_breaking=1
-g_tree_cut_reuse_dist=1
-p_max_entity_cells=75000
-p_max_MC_iters=2000
-p_max_substeps=2
-
-[2]
-es_MaxPhysDistInvisible=15
-e_CullVegActivation=30
-e_FoliageWindActivationDist=10
-e_PhysMinCellSize=16
-e_PhysOceanCell=1
-g_breakage_mem_limit=2000
-g_breakage_particles_limit=40
-g_no_secondary_breaking=1
-g_tree_cut_reuse_dist=1
-p_max_entity_cells=75000
-p_max_MC_iters=2000
-p_max_substeps=2
-
-[3]
-es_MaxPhysDistInvisible=15
-e_CullVegActivation=30
-e_FoliageWindActivationDist=10
-e_PhysMinCellSize=16
-e_PhysOceanCell=1
-g_breakage_mem_limit=2000
-g_breakage_particles_limit=40
-g_no_secondary_breaking=1
-g_tree_cut_reuse_dist=1
-p_max_entity_cells=75000
-p_max_MC_iters=2000
-p_max_substeps=2
-
-[4]
-es_MaxPhysDistInvisible=15
-e_CullVegActivation=30
-e_FoliageWindActivationDist=10
-e_PhysMinCellSize=16
-e_PhysOceanCell=1
-g_breakage_mem_limit=2000
-g_breakage_particles_limit=40
-g_no_secondary_breaking=1
-g_tree_cut_reuse_dist=1
-p_max_entity_cells=75000
-p_max_MC_iters=2000
-p_max_substeps=2
-
-[5]
-es_MaxPhysDist=50
-es_MaxPhysDistInvisible=15
-e_CullVegActivation=30
-e_FoliageWindActivationDist=10
-e_PhysOceanCell=1
-g_breakage_particles_limit=80
-g_tree_cut_reuse_dist=0.35
-p_max_MC_iters=4000
-p_max_substeps=2
-
-[6]
-
-[8]
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_PostProcessing.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_PostProcessing.cfg
deleted file mode 100644
index 9d2cd3754d..0000000000
--- a/Assets/Engine/Config/CVarGroups/sys_spec_PostProcessing.cfg
+++ /dev/null
@@ -1,114 +0,0 @@
-[default]
-; default of this CVarGroup
-= 7
-
-r_PostProcessEffects=1
-q_ShaderHDR=2
-q_ShaderPostProcess=2
-r_ChromaticAberration=0
-r_ColorGradingChartsCache=0
-r_DepthOfField=2
-r_Flares=1
-r_HDRBloomQuality=2
-r_MotionBlur=2
-r_MotionBlurMaxViewDist=100000
-r_MotionBlurQuality=1
-r_MotionBlurShutterSpeed=125
-r_Rain=2
-r_RainMaxViewDist_Deferred=150
-r_Sharpening=0
-r_Snow=2
-r_SunShafts=2
-r_TranspDepthFixup=1
-r_ToneMapTechnique=0
-r_ToneMapExposureType=0
-r_HDRBloom=1
-r_ColorGrading=1
-r_ColorSpace=0
-
-[1]
-q_ShaderHDR=1
-q_ShaderPostProcess=1
-r_ColorGrading=0
-r_DepthOfField=0
-r_Flares=0
-r_HDRBloom=0
-r_HDRBloomQuality=0
-r_MotionBlur=0
-r_MotionBlurMaxViewDist=16
-r_MotionBlurQuality=0
-r_Rain=1
-r_RainMaxViewDist_Deferred=40
-r_Snow=1
-r_SunShafts=0
-r_TranspDepthFixup=0
-r_ToneMapTechnique=3
-r_ToneMapExposureType=1
-r_ColorSpace=2
-
-
-[2]
-q_ShaderHDR=1
-q_ShaderPostProcess=1
-r_ColorGradingChartsCache=4
-r_DepthOfField=1
-r_Flares=0
-r_HDRBloomQuality=0
-r_MotionBlur=0
-r_MotionBlurMaxViewDist=16
-r_MotionBlurQuality=0
-r_Rain=1
-r_RainMaxViewDist_Deferred=40
-r_Snow=1
-r_SunShafts=1
-r_TranspDepthFixup=0
-
-
-[3]
-q_ShaderHDR=1
-q_ShaderPostProcess=2
-r_ColorGradingChartsCache=4
-r_DepthOfField=1
-r_HDRBloomQuality=1
-r_MotionBlur=0
-r_MotionBlurMaxViewDist=16
-r_MotionBlurQuality=0
-r_Rain=1
-r_RainMaxViewDist_Deferred=40
-r_Snow=1
-r_SunShafts=1
-r_TranspDepthFixup=0
-
-[4]
-q_ShaderHDR=1
-q_ShaderPostProcess=2
-r_ColorGradingChartsCache=4
-r_DepthOfField=1
-r_HDRBloomQuality=1
-r_MotionBlur=0
-r_MotionBlurMaxViewDist=16
-r_MotionBlurQuality=0
-r_Rain=1
-r_RainMaxViewDist_Deferred=40
-r_Snow=1
-r_SunShafts=1
-r_TranspDepthFixup=0
-
-[5]
-q_ShaderHDR=1
-q_ShaderPostProcess=1
-r_ColorGradingChartsCache=4
-r_MotionBlurMaxViewDist=16
-r_MotionBlurQuality=0
-r_RainMaxViewDist_Deferred=40
-r_TranspDepthFixup=0
-
-[6]
-q_ShaderHDR=1
-q_ShaderPostProcess=1
-r_RainMaxViewDist_Deferred=100
-
-[8]
-q_ShaderHDR=3
-q_ShaderPostProcess=3
-r_MotionBlurQuality=2
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Quality.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Quality.cfg
deleted file mode 100644
index cf1bdf5184..0000000000
--- a/Assets/Engine/Config/CVarGroups/sys_spec_Quality.cfg
+++ /dev/null
@@ -1,98 +0,0 @@
-[default]
-; default of this CVarGroup
-= 7
-
-q_ShaderGeneral=2
-q_ShaderMetal=2
-q_ShaderGlass=2
-q_ShaderVegetation=2
-q_ShaderIce=2
-q_ShaderTerrain=2
-q_ShaderShadow=2
-q_ShaderFX=2
-q_ShaderSky=2
-q_Renderer=2
-
-[1]
-q_ShaderGeneral=1
-q_ShaderMetal=1
-q_ShaderGlass=1
-q_ShaderVegetation=1
-q_ShaderIce=1
-q_ShaderTerrain=1
-q_ShaderShadow=1
-q_ShaderFX=1
-q_ShaderSky=1
-q_Renderer=1
-
-[2]
-q_ShaderGeneral=1
-q_ShaderMetal=1
-q_ShaderGlass=1
-q_ShaderVegetation=1
-q_ShaderIce=1
-q_ShaderTerrain=1
-q_ShaderShadow=1
-q_ShaderFX=1
-q_ShaderSky=1
-q_Renderer=1
-
-[3]
-q_ShaderGeneral=1
-q_ShaderMetal=1
-q_ShaderGlass=1
-q_ShaderVegetation=1
-q_ShaderIce=1
-q_ShaderTerrain=1
-q_ShaderShadow=1
-q_ShaderFX=1
-q_ShaderSky=1
-q_Renderer=2
-
-[4]
-q_ShaderGeneral=1
-q_ShaderMetal=1
-q_ShaderGlass=1
-q_ShaderVegetation=1
-q_ShaderIce=1
-q_ShaderTerrain=1
-q_ShaderShadow=1
-q_ShaderFX=1
-q_ShaderSky=1
-q_Renderer=2
-
-[5]
-q_ShaderGeneral=1
-q_ShaderMetal=1
-q_ShaderGlass=1
-q_ShaderVegetation=1
-q_ShaderIce=1
-q_ShaderTerrain=1
-q_ShaderShadow=1
-q_ShaderFX=1
-q_ShaderSky=1
-q_Renderer=1
-
-[6]
-q_ShaderGeneral=1
-q_ShaderMetal=1
-q_ShaderGlass=1
-q_ShaderVegetation=1
-q_ShaderIce=1
-q_ShaderTerrain=1
-q_ShaderShadow=1
-q_ShaderFX=1
-q_ShaderSky=1
-q_Renderer=1
-
-[8]
-q_ShaderGeneral=3
-q_ShaderMetal=3
-q_ShaderGlass=3
-q_ShaderVegetation=3
-q_ShaderIce=3
-q_ShaderTerrain=3
-q_ShaderShadow=3
-q_ShaderFX=3
-q_ShaderSky=3
-q_Renderer=3
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Shading.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Shading.cfg
deleted file mode 100644
index eb379a8583..0000000000
--- a/Assets/Engine/Config/CVarGroups/sys_spec_Shading.cfg
+++ /dev/null
@@ -1,120 +0,0 @@
-[default]
-; default of this CVarGroup
-= 7
-
-e_CacheNearestCubePicking=1
-e_DynamicLightsMaxEntityLights=16
-e_GI=1
-e_LightVolumes=1
-e_SkyUpdateRate=1
-e_TerrainAo=0
-e_VegetationUseTerrainColor=1
-r_DeferredShadingDepthBoundsTest=1
-r_DeferredShadingTiled=2
-r_DeferredShadingTiledHairQuality=1
-r_deferredShadingFilterGBuffer=0
-r_DeferredShadingSSS=1
-r_AntialiasingMode=3
-r_DetailDistance=8
-r_EnvTexUpdateInterval=0.05
-r_Refraction=1
-r_RefractionPartialResolves=2
-r_ssdo=1
-r_ssdoHalfRes=2
-r_ssdoColorBleeding=1
-r_SSReflections=1
-r_SSReflHalfRes=1
-r_VisAreaClipLightsPerPixel=1
-sys_spec_Quality=7
-
-[1]
-e_DynamicLightsMaxEntityLights=2
-e_GI=0
-e_SkyUpdateRate=0.5
-e_VegetationUseTerrainColor=0
-r_DeferredShadingTiled=0
-r_DeferredShadingTiledHairQuality=0
-r_DeferredShadingSSS=0
-r_AntialiasingMode=0
-r_DetailDistance=4
-r_EnvTexUpdateInterval=0.075
-r_Refraction=0
-r_RefractionPartialResolves=0
-r_ssdo=0
-r_ssdoHalfRes=1
-r_ssdoColorBleeding=0
-r_SSReflections=0
-sys_spec_Quality=1
-
-[2]
-e_DynamicLightsMaxEntityLights=2
-e_GI=0
-e_SkyUpdateRate=0.5
-e_VegetationUseTerrainColor=0
-r_DeferredShadingTiled=0
-r_DeferredShadingTiledHairQuality=0
-r_DeferredShadingSSS=0
-r_AntialiasingMode=0
-r_DetailDistance=4
-r_EnvTexUpdateInterval=0.075
-r_RefractionPartialResolves=0
-r_ssdo=0
-r_ssdoHalfRes=1
-r_ssdoColorBleeding=0
-r_SSReflections=0
-sys_spec_Quality=2
-
-[3]
-e_DynamicLightsMaxEntityLights=2
-e_GI=0
-e_SkyUpdateRate=0.5
-e_VegetationUseTerrainColor=0
-r_DeferredShadingTiled=0
-r_DeferredShadingTiledHairQuality=0
-r_DeferredShadingSSS=0
-r_AntialiasingMode=0
-r_DetailDistance=4
-r_EnvTexUpdateInterval=0.075
-r_RefractionPartialResolves=0
-r_ssdo=0
-r_ssdoColorBleeding=0
-r_SSReflections=0
-sys_spec_Quality=3
-
-[4]
-e_DynamicLightsMaxEntityLights=2
-e_GI=0
-e_SkyUpdateRate=0.5
-e_VegetationUseTerrainColor=0
-r_DeferredShadingTiled=0
-r_DeferredShadingTiledHairQuality=0
-r_DeferredShadingSSS=0
-r_AntialiasingMode=0
-r_DetailDistance=4
-r_EnvTexUpdateInterval=0.075
-r_RefractionPartialResolves=0
-r_ssdo=1
-r_ssdoHalfRes=1
-r_ssdoColorBleeding=0
-r_SSReflections=0
-sys_spec_Quality=4
-
-[5]
-e_DynamicLightsMaxEntityLights=7
-e_GI=0
-e_SkyUpdateRate=0.5
-r_DetailDistance=4
-r_EnvTexUpdateInterval=0.075
-r_SSReflections=0
-r_DeferredShadingTiledHairQuality=0
-r_DeferredShadingSSS=0
-sys_spec_Quality=5
-
-[6]
-e_DynamicLightsMaxEntityLights=11
-sys_spec_Quality=6
-
-[8]
-r_DeferredShadingTiledHairQuality=2
-r_SSReflHalfRes=0
-sys_spec_Quality=8
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Shadows.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Shadows.cfg
deleted file mode 100644
index d43c28c09d..0000000000
--- a/Assets/Engine/Config/CVarGroups/sys_spec_Shadows.cfg
+++ /dev/null
@@ -1,116 +0,0 @@
-[default]
-; default of this CVarGroup
-= 7
-
-e_GsmLodsNum=5
-e_GsmRange=3
-e_ParticlesShadows=1
-e_Shadows=1
-e_ShadowsBlendCascades=1
-e_ShadowsClouds=1
-e_ShadowsCastViewDistRatio=1
-e_ShadowsLodBiasFixed=0
-e_ShadowsMaxTexRes=1024
-e_ShadowsOnAlphaBlend=0
-e_ShadowsPoolSize=4096
-e_ShadowsResScale=4
-e_ShadowsTessellateCascades=1
-e_ShadowsTessellateDLights=0
-e_ShadowsUpdateViewDistRatio=256
-r_DrawNearShadows=1
-r_FogShadows=2
-r_FogShadowsWater=0
-r_ShadowJittering=2.5
-r_ShadowPoolMaxFrames=30
-r_ShadowPoolMaxTimeslicedUpdatesPerFrame=100
-r_ShadowsPCFiltering=1
-r_ShadowsCache=4
-r_ShadowsCacheFormat=1
-r_ShadowsCacheResolutions=6324,4214
-r_ShadowsUseClipVolume=1
-e_ObjShadowCastSpec=3
-
-[1]
-e_GsmLodsNum=3
-e_ParticlesShadows=0
-e_ShadowsBlendCascades=0
-e_ShadowsCastViewDistRatio=0.8
-e_ShadowsLodBiasFixed=1
-e_ShadowsMaxTexRes=512
-r_DrawNearShadows=0
-r_FogShadows=0
-r_ShadowJittering=0
-r_ShadowsCacheFormat=0
-r_ShadowsCacheResolutions=3162,2107
-e_ObjShadowCastSpec=1
-e_ShadowsPoolSize=1024
-
-[2]
-e_GsmLodsNum=4
-e_ParticlesShadows=0
-e_ShadowsBlendCascades=0
-e_ShadowsCastViewDistRatio=0.8
-e_ShadowsLodBiasFixed=1
-e_ShadowsMaxTexRes=512
-r_DrawNearShadows=0
-r_FogShadows=0
-r_ShadowJittering=0
-r_ShadowsCacheFormat=0
-r_ShadowsCacheResolutions=3162,2107
-e_ObjShadowCastSpec=1
-e_ShadowsPoolSize=1024
-
-[3]
-e_GsmLodsNum=4
-e_ParticlesShadows=0
-e_ShadowsBlendCascades=0
-e_ShadowsCastViewDistRatio=0.8
-e_ShadowsLodBiasFixed=1
-e_ShadowsMaxTexRes=512
-r_DrawNearShadows=0
-r_FogShadows=0
-r_ShadowJittering=0
-r_ShadowsCacheFormat=0
-r_ShadowsCacheResolutions=3162,2107
-e_ObjShadowCastSpec=1
-e_ShadowsPoolSize=1024
-
-[4]
-e_GsmLodsNum=4
-e_ParticlesShadows=0
-e_ShadowsBlendCascades=0
-e_ShadowsCastViewDistRatio=0.8
-e_ShadowsLodBiasFixed=1
-e_ShadowsMaxTexRes=512
-r_DrawNearShadows=0
-r_FogShadows=0
-r_ShadowJittering=0
-r_ShadowsCacheFormat=0
-r_ShadowsCacheResolutions=3162,2107
-e_ObjShadowCastSpec=1
-e_ShadowsPoolSize=1024
-
-[5]
-e_GsmLodsNum=4
-e_ParticlesShadows=0
-e_ShadowsBlendCascades=0
-e_ShadowsCastViewDistRatio=0.8
-e_ShadowsLodBiasFixed=1
-e_ShadowsMaxTexRes=512
-r_FogShadows=0
-r_ShadowJittering=1
-e_ObjShadowCastSpec=1
-r_ShadowsCacheResolutions=3162,2107
-
-[6]
-r_ShadowJittering=1
-e_ObjShadowCastSpec=2
-
-[8]
-r_FogShadows=1
-r_FogShadowsWater=1
-r_ShadowPoolMaxFrames=0
-r_ShadowPoolMaxTimeslicedUpdatesPerFrame=100
-e_ObjShadowCastSpec=4
-r_ShadowsCache=5
-r_ShadowsCacheResolutions=4214
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Sound.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Sound.cfg
deleted file mode 100644
index 42bd4c7f02..0000000000
--- a/Assets/Engine/Config/CVarGroups/sys_spec_Sound.cfg
+++ /dev/null
@@ -1,17 +0,0 @@
-[default]
-; default of this CVarGroup
-= 7
-
-[1]
-
-[2]
-
-[3]
-
-[4]
-
-[5]
-
-[6]
-
-[8]
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Texture.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Texture.cfg
deleted file mode 100644
index 0e02c41ab2..0000000000
--- a/Assets/Engine/Config/CVarGroups/sys_spec_Texture.cfg
+++ /dev/null
@@ -1,94 +0,0 @@
-[default]
-; default of this CVarGroup
-= 7
-
-e_TerrainTextureStreamingPoolItemsNum=64
-r_DynTexAtlasCloudsMaxSize=32
-r_DynTexAtlasSpritesMaxSize=32
-r_DynTexMaxSize=80
-r_EnvCMResolution=2
-r_EnvTexResolution=3
-r_ImposterRatio=1
-r_TexAtlasSize=2048
-r_TexMaxAnisotropy=4
-r_TexMinAnisotropy=4
-r_TexNoAnisoAlphaTest=0
-
-[1]
-e_TerrainTextureStreamingPoolItemsNum=16
-r_DynTexAtlasCloudsMaxSize=8
-r_DynTexAtlasSpritesMaxSize=8
-r_DynTexMaxSize=20
-r_EnvCMResolution=0
-r_EnvTexResolution=1
-r_ImposterRatio=2
-r_TexAtlasSize=512
-r_TexMaxAnisotropy=2
-r_TexMinAnisotropy=2
-r_TexNoAnisoAlphaTest=1
-
-[2]
-e_TerrainTextureStreamingPoolItemsNum=16
-r_DynTexAtlasCloudsMaxSize=8
-r_DynTexAtlasSpritesMaxSize=8
-r_DynTexMaxSize=20
-r_EnvCMResolution=0
-r_EnvTexResolution=1
-r_ImposterRatio=2
-r_TexAtlasSize=512
-r_TexMaxAnisotropy=2
-r_TexMinAnisotropy=2
-r_TexNoAnisoAlphaTest=1
-
-[3]
-e_TerrainTextureStreamingPoolItemsNum=16
-r_DynTexAtlasCloudsMaxSize=8
-r_DynTexAtlasSpritesMaxSize=8
-r_DynTexMaxSize=20
-r_EnvCMResolution=0
-r_EnvTexResolution=1
-r_ImposterRatio=2
-r_TexAtlasSize=512
-r_TexMaxAnisotropy=2
-r_TexMinAnisotropy=2
-r_TexNoAnisoAlphaTest=1
-
-[4]
-e_TerrainTextureStreamingPoolItemsNum=16
-r_DynTexAtlasCloudsMaxSize=8
-r_DynTexAtlasSpritesMaxSize=8
-r_DynTexMaxSize=20
-r_EnvCMResolution=0
-r_EnvTexResolution=1
-r_ImposterRatio=2
-r_TexAtlasSize=512
-r_TexMaxAnisotropy=2
-r_TexMinAnisotropy=2
-r_TexNoAnisoAlphaTest=1
-
-[5]
-r_DynTexAtlasCloudsMaxSize=24
-r_DynTexAtlasSpritesMaxSize=16
-r_DynTexMaxSize=50
-r_EnvCMResolution=0
-r_EnvTexResolution=1
-r_ImposterRatio=2
-r_TexAtlasSize=512
-r_TexMaxAnisotropy=2
-r_TexMinAnisotropy=2
-r_TexNoAnisoAlphaTest=1
-
-[6]
-r_DynTexAtlasCloudsMaxSize=24
-r_DynTexAtlasSpritesMaxSize=16
-r_DynTexMaxSize=60
-r_EnvCMResolution=1
-r_EnvTexResolution=2
-r_ImposterRatio=1.5
-r_TexMaxAnisotropy=8
-r_TexMinAnisotropy=8
-r_TexNoAnisoAlphaTest=1
-
-[8]
-r_TexMaxAnisotropy=16
-r_TexMinAnisotropy=16
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_TextureResolution.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_TextureResolution.cfg
deleted file mode 100644
index 6b6c11ddf6..0000000000
--- a/Assets/Engine/Config/CVarGroups/sys_spec_TextureResolution.cfg
+++ /dev/null
@@ -1,52 +0,0 @@
-[default]
-; dummy default for this CVarGroup (will be auto initialized during streaming system init or overridden by user via system.cfg)
-= 0
-
-; VRAM 1.0 GB
-r_TexturesStreaming=1
-r_TexturesStreamingMipBias=0
-r_TexturesstreamingMinUsableMips=8
-r_TexturesStreamingSkipMips=2
-r_TexturesStreamPoolSize=256
-
-[1]
-; VRAM 1.0 GB
-r_TexturesStreaming=0
-r_TexturesStreamingSkipMips=0
-r_TexturesStreamPoolSize=384
-
-[2]
-; VRAM 1.0 GB
-r_TexturesStreaming=0
-r_TexturesStreamingSkipMips=0
-r_TexturesStreamPoolSize=384
-
-[3]
-; VRAM 1.0 GB
-r_TexturesStreaming=0
-r_TexturesStreamingSkipMips=0
-r_TexturesStreamPoolSize=384
-
-[4]
-; VRAM 1.0 GB
-r_TexturesStreaming=0
-r_TexturesStreamingSkipMips=0
-r_TexturesStreamPoolSize=384
-
-[5]
-; VRAM 1.0 GB
-
-[6]
-; VRAM 1.5 GB
-r_TexturesStreamingSkipMips=1
-r_TexturesStreamPoolSize=512
-
-[7]
-; VRAM 2.0 GB
-r_TexturesStreamingSkipMips=0
-r_TexturesStreamPoolSize=640
-
-[8]
-; VRAM 3.0 GB
-r_TexturesStreamingSkipMips=0
-r_TexturesStreamPoolSize=1536
\ No newline at end of file
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_VolumetricEffects.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_VolumetricEffects.cfg
deleted file mode 100644
index b6fdfec33c..0000000000
--- a/Assets/Engine/Config/CVarGroups/sys_spec_VolumetricEffects.cfg
+++ /dev/null
@@ -1,26 +0,0 @@
-[default]
-; default of this CVarGroup
-= 7
-
-e_Clouds=1
-r_Beams=1
-
-[1]
-r_Beams=0
-
-[2]
-r_Beams=0
-
-[3]
-r_Beams=0
-
-[4]
-r_Beams=0
-
-[5]
-r_Beams=0
-
-[6]
-r_Beams=0
-
-[8]
diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Water.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Water.cfg
deleted file mode 100644
index 720339dc98..0000000000
--- a/Assets/Engine/Config/CVarGroups/sys_spec_Water.cfg
+++ /dev/null
@@ -1,81 +0,0 @@
-[default]
-; default of this CVarGroup
-= 7
-
-e_WaterOceanFFT=1
-e_WaterTessellationAmount=10
-e_WaterTessellationSwathWidth=10
-q_ShaderWater=2
-r_WaterCaustics=1
-r_WaterReflections=1
-r_WaterReflectionsQuality=4
-r_WaterReflectionsMinVisiblePixelsUpdate=0.05
-r_WaterTessellationHW=0
-r_WaterUpdateDistance=0.2
-r_WaterUpdateFactor=0.0
-r_WaterVolumeCaustics=0
-r_WaterVolumeCausticsDensity=256
-r_WaterVolumeCausticsMaxDist=35
-r_WaterVolumeCausticsRes=1024
-r_WaterVolumeCausticsSnapFactor=1
-
-[1]
-e_WaterTessellationAmount=20
-q_ShaderWater=1
-r_WaterReflectionsQuality=0
-r_WaterUpdateDistance=1
-r_WaterUpdateFactor=0.1
-r_WaterVolumeCausticsDensity=64
-r_WaterVolumeCausticsMaxDist=20
-r_WaterVolumeCausticsRes=384
-
-[2]
-e_WaterTessellationAmount=20
-q_ShaderWater=1
-r_WaterReflectionsQuality=0
-r_WaterUpdateDistance=1
-r_WaterUpdateFactor=0.1
-r_WaterVolumeCausticsDensity=64
-r_WaterVolumeCausticsMaxDist=20
-r_WaterVolumeCausticsRes=384
-
-[3]
-e_WaterTessellationAmount=20
-q_ShaderWater=1
-r_WaterReflectionsQuality=0
-r_WaterUpdateDistance=1
-r_WaterUpdateFactor=0.05
-r_WaterVolumeCausticsDensity=64
-r_WaterVolumeCausticsMaxDist=20
-r_WaterVolumeCausticsRes=384
-
-[4]
-e_WaterTessellationAmount=20
-q_ShaderWater=1
-r_WaterReflectionsQuality=4
-r_WaterUpdateDistance=1
-r_WaterUpdateFactor=0.01
-r_WaterVolumeCausticsDensity=64
-r_WaterVolumeCausticsMaxDist=20
-r_WaterVolumeCausticsRes=384
-
-[5]
-e_WaterTessellationAmount=20
-q_ShaderWater=1
-r_WaterUpdateDistance=1
-r_WaterUpdateFactor=0.1
-r_WaterVolumeCausticsDensity=64
-r_WaterVolumeCausticsMaxDist=20
-r_WaterVolumeCausticsRes=384
-
-[6]
-r_WaterUpdateDistance=1
-r_WaterUpdateFactor=0.05
-r_WaterVolumeCausticsDensity=128
-r_WaterVolumeCausticsMaxDist=25
-r_WaterVolumeCausticsRes=512
-
-[8]
-e_WaterTessellationAmount=85
-r_WaterTessellationHW=1
-r_WaterVolumeCaustics=1
diff --git a/Assets/Engine/Config/aidebug.cfg b/Assets/Engine/Config/aidebug.cfg
index f8134c7461..b0eafaaa45 100644
--- a/Assets/Engine/Config/aidebug.cfg
+++ b/Assets/Engine/Config/aidebug.cfg
@@ -1,4 +1 @@
ai_DebugDraw = 1
-ai_DebugDrawNavigation = 1
-ai_DrawPath all
-ai_debugMNMAgentType MediumSizedCharacters
\ No newline at end of file
diff --git a/Assets/Engine/Config/artprof.cfg b/Assets/Engine/Config/artprof.cfg
index 2e1cf55a54..92b91623bf 100644
--- a/Assets/Engine/Config/artprof.cfg
+++ b/Assets/Engine/Config/artprof.cfg
@@ -1,7 +1,6 @@
; Setup useful cvars for artists profiling GPU cost
; Once in level (e.g. map c3mp_rooftop_gardens from the frontend/cmdline), in the console:
; exec artprof.cfg
-; Be sure also to set r_shadersAsyncActivation=0 in your user.cfg (or copy artprof_user.cfg -> user.cfg)
; used to allow loading of loose shaders
sys_pakPriority=0
@@ -9,19 +8,8 @@ sys_pakPriority=0
; because it's annoying and not relevant for artists
sys_pakLogInvalidFileAccess=0
-; disable fog volumes and particles as they can be misleading with r_measureOverdraw 4
-e_fogVolumes=0
-e_particles=0
-
; for convenience
-g_infiniteSuitEnergy=1
-g_infiniteAmmo=1
-g_timelimit=0
+
bind o "r_measureOverdraw 0"
bind p "r_measureOverdraw 4"
-bind k "r_artProfile 0"
-bind l "r_artProfile 1"
-
-; loading into an MP level with the map command stops you looking up and down unless you have a weapon
-i_giveitem scar
diff --git a/Assets/Engine/Config/artprof_user.cfg b/Assets/Engine/Config/artprof_user.cfg
index 673436f6f3..265021e120 100644
--- a/Assets/Engine/Config/artprof_user.cfg
+++ b/Assets/Engine/Config/artprof_user.cfg
@@ -1,6 +1,3 @@
-; disable async shader activation as it crashes when r_shadersAllowCompilation=1
-r_shadersAsyncActivation=0
-
; enable shader compiliation for r_measureOverdraw 4
r_shadersAllowCompilation=1
diff --git a/Assets/Engine/Config/benchmark_cpu.cfg b/Assets/Engine/Config/benchmark_cpu.cfg
index c75619107f..bbb3c9db95 100644
--- a/Assets/Engine/Config/benchmark_cpu.cfg
+++ b/Assets/Engine/Config/benchmark_cpu.cfg
@@ -1,13 +1,3 @@
-demo_restart_level = 2
-g_godMode=1
-g_infiniteammo=1
r_displayinfo=1
-demo_file = autotest
-demo_ai = 1
-demo_num_runs = 4
-demo_quit = 1
-hud_startPaused=0
sys_maxfps=0
-e_ObjectLayersActivation=0
-sys_flash = 0
r_vsync = 0
diff --git a/Assets/Engine/Config/benchmark_gpu.cfg b/Assets/Engine/Config/benchmark_gpu.cfg
index 7653b32d86..f0242d64d1 100644
--- a/Assets/Engine/Config/benchmark_gpu.cfg
+++ b/Assets/Engine/Config/benchmark_gpu.cfg
@@ -1,13 +1,3 @@
-demo_restart_level = 1
-g_godMode = 1
-g_infiniteammo = 1
r_displayinfo = 2
-demo_file = timedemo_short
-demo_ai = 0
-demo_num_runs = 2
-demo_quit = 1
--- hud_startPaused = 0
sys_maxfps = -1
--- e_ObjectLayersActivation = 0
--- sys_flash = 0
-r_vsync = 0
\ No newline at end of file
+r_vsync = 0
diff --git a/Assets/Engine/Config/mgpu.cfg b/Assets/Engine/Config/mgpu.cfg
index 93da7fdfd0..e69de29bb2 100644
--- a/Assets/Engine/Config/mgpu.cfg
+++ b/Assets/Engine/Config/mgpu.cfg
@@ -1,6 +0,0 @@
-r_ColorGradingChartsCache = 0
-r_waterupdateFactor = 0
-r_PostProcessHUD3DCache = 0
-e_gsmcache = 0
-r_ConditionalRendering = 0
-e_gicache = 0
\ No newline at end of file
diff --git a/Assets/Engine/Config/multiplayer.cfg b/Assets/Engine/Config/multiplayer.cfg
index eafa434f8e..e69de29bb2 100644
--- a/Assets/Engine/Config/multiplayer.cfg
+++ b/Assets/Engine/Config/multiplayer.cfg
@@ -1,77 +0,0 @@
-ag_turnSpeedParamScale=0.0
-aim_assistFalloffDistance=200
-aim_assistInputForFullFollow_Ironsight=0.20
-aim_assistMaxDistance=255
-aim_assistMaxDistance_ironsight=255
-aim_assistMinTurnScale=0.5
-aim_assistMinTurnScale_ironsight=0.5
-aim_assistSlowDisableDistance=255
-aim_assistSlowFalloffStartDistance=200
-aim_assistSlowThresholdOuter=2.5
-aim_assiststrength=0.7
-aim_assiststrength_ironsight=0.75
-br_breakmaxworldsize=511
-cl_sensitivityControllerMP=0.6
-cl_shallowWaterSpeedMulPlayer=1.0
-controller_multiplier_x=3
-controller_multiplier_z=4
-g_actorViewDistRatio=255
-
--- This forces broken trees to have spherical inertia, which makes them harder to rotate around their vertical axis.
-g_breakageMinAxisInertia=1.0
-g_glassAutoShatterMinArea=0.5
-
-g_distanceForceNoIk=35
-g_fpDbaManagementEnable=0
-g_godMode=0
-g_highlightingMaxDistanceToHighlightSquared=625
-g_hitDeathReactions_streaming=2
-g_mp_as_DefendersMaxHealth=150
-g_multiplayerDefault=1
-
--- Overriden in GameSDK\Difficulty\*.cfg
-g_playerLowHealthThreshold=20
-g_playerMidHealthThreshold=60
-
-g_spawn_vistable_numLineTestsPerFrame=3
-g_telemetryConfig="MP"
-g_telemetrySampleRateBandwidth=3
-g_telemetrySampleRateMemory=2
-g_telemetrySampleRatePerformance=1
-g_VTOLInsideBoundsScaleX=0.6
-g_VTOLInsideBoundsScaleY=1
-net_breakage_sync_entities=0
-net_enable_tfrc=0
-net_log=1
-
--- Make consoles match the PC gravity
-p_gravity_z="-13"
-
--- Sanity check for physics RepositionEntity
-p_max_entity_cells=10000
-
-pl_impulseEnabled=1
-pl_jump_maxTimerValue=0.0
-pl_jump_quickPressThresh=0.12
-pl_melee.angle_limit_from_behind=70
-pl_melee.impulses_enable=1
-pl_melee.melee_snap_angle_limit=45
-pl_melee.melee_snap_end_position_range=1.5
-pl_melee.melee_snap_move_speed_multiplier=10
-pl_melee.melee_snap_target_select_range=3.5
-pl_melee.mp_knockback_strength_hor=2
-pl_melee.mp_melee_system=1
-pl_melee.mp_victim_screenfx_blendout_duration=0.25
-pl_melee.mp_victim_screenfx_duration=0.1
-pl_nanovision_timetodrain=8
-pl_nanovision_timetorecharge=16
-pl_pickAndThrow.chargedThrowAutoAimConeSize=10
-pl_pickAndThrow.complexMelee_snap_angle_limit=25
-pl_sliding_control_mp.deceleration_speed=4
-pl_sliding_control_mp.max_downhill_acceleration=15
-pl_sliding_control_mp.min_speed=4
-pl_sliding_control_mp.min_speed_threshold=5
-pl_stealthKill_aimVsSpineLerp=0.65
-pl_stealthKill_useExtendedRange=1
-p_splash_vel0=0.5
-sv_bandwidth=2147483647
\ No newline at end of file
diff --git a/Assets/Engine/Config/multiplayer_console.cfg b/Assets/Engine/Config/multiplayer_console.cfg
index 0bed002497..e69de29bb2 100644
--- a/Assets/Engine/Config/multiplayer_console.cfg
+++ b/Assets/Engine/Config/multiplayer_console.cfg
@@ -1,29 +0,0 @@
-e_GI=0
-r_DeferredShadingIndexedAmbient=0
-e_ParticlesObjectCollisions=0
-g_distanceForceNoLegRaycasts=0.00001
-g_telemetryDisplaySessionId=1
-g_breakageNoDebrisCollisions=1
-
-; Breakage throttling
-; These are explained in ActionGame.cpp
-;
-g_glassAutoShatterOnExplosions=1
-g_glassNoDecals=1
-g_glassMaxPanesToBreakPerFrame=2
-g_breakageTreeMax=100
-g_breakageTreeInc=101
-g_breakageTreeDec=25
-g_breakageTreeIncGlass=51
-
-sys_PakInMemoryPakSizeLimit=25
-
-r_TexturesStreamPoolSecondarySize=35
-r_MotionBlur=1
-
-e_CoverageBufferReproj=2
-
-osm_enabled = 1
-
-g_waterHitOnly = 1
-p_max_object_splashes=1
diff --git a/Assets/Engine/Config/recording.cfg b/Assets/Engine/Config/recording.cfg
index 42a0dfd9bd..931dbf0858 100644
--- a/Assets/Engine/Config/recording.cfg
+++ b/Assets/Engine/Config/recording.cfg
@@ -1,63 +1,3 @@
--- added this lines for proper 360 deg panorama renderings
-
-e_ScreenShotFileFormat = jpg
-demo_fixed_timestep = 60
-s_SoundEnable = 0
r_DisplayInfo = 0
-e_PanoramaScreenShotHeight = 720
-e_PanoramaScreenShotWidth = 10053
c_shakeMult = 0
-demo_ai = 1
-r_MotionBlur = 0
-
--- enables full water reflection
--- e_DebugMask = 2 -- e_DebugMask not allowed here
-
--- set weapong lighting effect to 0 to prevent flickering bug because of too much dynamic lights in the scene
-
-
sys_spec = 2
-r_WaterRefractions = 1
-r_WaterReflections = 1
-r_WaterUpdateFactor = 0.01
-r_WaterReflections_ForceParticles = 0
-
-r_EnvCMResolution = 2
-r_EnvTexResolution = 3
-r_EnvTexUpdateInterval = 0.05
-e_Decals = 1
-e_DecalsLifeTimeScale = 2
-ca_EnableDecals = 1
-e_LodRatio = 10
-e_ViewDistRatio = 55
-e_Lods = 1
-e_VegetationMinSize = 0
-r_CloudsUpdateAlways = 0
-
-e_DynamicLightsMaxEntityLights = 3
-r_DepthOfField = 1
---r_MotionBlur = 1
-r_Flares = 1
-r_checkSunVis = 1
-r_Coronas = 1
-r_CoronaFade = 0.1625
-r_UseEdgeAA = 1
-e_Clouds = 1
-
-r_TexResolution = 0
-r_TexBumpResolution = 0
-r_DetailTextures = 1
-r_DetailNumLayers = 1
-r_DetailDistance = 8
-
-e_ParticlesLod = 0.9
-
-r_ShadowBlur = 3
-e_ShadowsMaxTexRes = 1024
-r_ShadowJittering = 1
-e_Shadows = 1
-e_VegetationBending = 1
-ai_UpdateAllAlways = 1
-r_refraction = 1
-r_sunshafts = 1
-r_ImposterRatio = 1
diff --git a/Assets/Engine/Config/singleplayer.cfg b/Assets/Engine/Config/singleplayer.cfg
index fc7a4f4c05..e69de29bb2 100644
--- a/Assets/Engine/Config/singleplayer.cfg
+++ b/Assets/Engine/Config/singleplayer.cfg
@@ -1,15 +0,0 @@
-ai_CompatibilityMode=crysis2
-ai_BurstWhileMovingDestinationRange=9999.0
-
-g_telemetryConfig=SP
-
-net_inactivitytimeout=3600
-net_inactivitytimeoutDevmode=3600
-
-pl_movement.nonCombat_heavy_weapon_speed_scale=1.0
-
--- BLM - Don't override game rules. The template project only has DummyRules.
--- Furthermore, multiplayer.cfg doesn't set sv_gamerules, so the inconsistency
--- is likely to create bugs.
---sv_gamerules=SinglePlayer
-ca_StreamCHR=1
\ No newline at end of file
diff --git a/Assets/Engine/Config/sketch_off.cfg b/Assets/Engine/Config/sketch_off.cfg
deleted file mode 100644
index 6b0562daab..0000000000
--- a/Assets/Engine/Config/sketch_off.cfg
+++ /dev/null
@@ -1,24 +0,0 @@
-r_UseZPass = 1
-r_GeomInstancing = 1
-
-e_Fog = 1
-e_Clouds = 1
-e_Decals = 1
-e_TerrainDetailMaterials = 1
-e_Dissolve = 1
-e_TerrainAo = 1
-
-r_WaterReflections = 1
-
-e_Shadows = 1
-e_VegetationBending = 1
-
-r_PostProcessEffects = 1
-r_Flares = 1
-r_Beams = 1
-r_Glow = 1
-
-r_DetailTextures = 1
-
-r_refraction = 1
-r_sunshafts = 1
\ No newline at end of file
diff --git a/Assets/Engine/Config/sketch_on.cfg b/Assets/Engine/Config/sketch_on.cfg
deleted file mode 100644
index 6759b5d4c8..0000000000
--- a/Assets/Engine/Config/sketch_on.cfg
+++ /dev/null
@@ -1,24 +0,0 @@
-r_UseZPass = 0
-r_GeomInstancing = 0
-
-e_Fog = 0
-e_Clouds = 0
-e_Decals = 0
-e_TerrainDetailMaterials = 0
-e_Dissolve = 0
-e_TerrainAo = 0
-
-r_WaterReflections = 0
-
-e_Shadows = 0
-e_VegetationBending = 0
-
-r_PostProcessEffects = 0
-r_Flares = 0
-r_Beams = 0
-r_Glow = 0
-
-r_DetailTextures = 0
-
-r_refraction = 0
-r_sunshafts = 0
\ No newline at end of file
diff --git a/Assets/Engine/Config/spec/android_MaliT760.cfg b/Assets/Engine/Config/spec/android_MaliT760.cfg
index f951e61eef..fd7c0a349d 100644
--- a/Assets/Engine/Config/spec/android_MaliT760.cfg
+++ b/Assets/Engine/Config/spec/android_MaliT760.cfg
@@ -1,76 +1,8 @@
-sys_spec_Full=2
-
-- Cap frame rate at 30fps
sys_maxfps=30
r_vsync=0
--- Disable gmem for this device because it causes a crash
-r_EnableGMEMPath=0
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
-sys_job_system_max_worker=2
sys_streaming_in_blocks=1
sys_streaming_memory_budget=512
--- This allows the generation of reflections for the ocean water. Without it, the water looks really dark.
-e_recursion=1
-e_CheckOcclusion=1
-
-r_Fur=0
-az_Asset_EnableAsyncMeshLoading=0
-
-------------------------
--- Misc. memory buffers
-------------------------
-e_GeomCacheBufferSize=0
-e_CheckOcclusionQueueSize=512
-e_CheckOcclusionOutputQueueSize=1024
-
-------------------------
--- Animation
-------------------------
-ca_MemoryDefragPoolSize=33554432
-ca_StreamCHR=1
-
-------------------------
--- sys_spec_objectdetail
-------------------------
-e_Dissolve=2
-e_LodRatio=5
-e_ViewDistRatioDetail=19
-e_ViewDistRatioVegetation=21
-
-
-------------------------
--- sys_spec_postprocessing
-------------------------
-r_HDRBloom=0
-r_SunShafts=0
-r_ToneMapTechnique=3
-r_ToneMapExposureType=1
-r_ColorSpace=2
-
-------------------------
--- sys_spec_shading
-------------------------
-r_VisAreaClipLightsPerPixel=0
-
-------------------------
--- sys_spec_textureresolution
-------------------------
-r_TexturesstreamingMinUsableMips=7
-
-
-
--- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame.
--- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame.
--- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps
-e_ShadowsCacheRequireManualUpdate = 2
-
---Use an optimized pixel format for the lighting rendertargets during the lighting pass.
-r_DeferredShadingLBuffersFmt = 2
\ No newline at end of file
diff --git a/Assets/Engine/Config/spec/android_high.cfg b/Assets/Engine/Config/spec/android_high.cfg
index fc46adc491..0ab8ebc37b 100644
--- a/Assets/Engine/Config/spec/android_high.cfg
+++ b/Assets/Engine/Config/spec/android_high.cfg
@@ -1,65 +1,7 @@
-sys_spec_Full=3
-
-- Cap frame rate at 30fps
sys_maxfps=30
r_vsync=0
--- Enable framebufferfetch(256bpp) or pls if applicable
-r_EnableGMEMPath=2
-
--- Skip the native upscale as a second upscale already occurs
-r_SkipNativeUpscale=1
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
-sys_job_system_max_worker=2
sys_streaming_in_blocks=1
sys_streaming_memory_budget=512
-
-e_CheckOcclusion=1
-
-r_Fur=0
-az_Asset_EnableAsyncMeshLoading=0
-
-------------------------
--- Misc. memory buffers
-------------------------
-e_GeomCacheBufferSize=0
-e_CheckOcclusionQueueSize=512
-e_CheckOcclusionOutputQueueSize=1024
-
-------------------------
--- Animation
-------------------------
-ca_MemoryDefragPoolSize=33554432
-ca_StreamCHR=1
-
-------------------------
--- sys_spec_objectdetail
-------------------------
-e_Dissolve=2
-e_LodRatio=5
-e_ViewDistRatioDetail=19
-
-
-------------------------
--- sys_spec_shading
-------------------------
-r_VisAreaClipLightsPerPixel=0
-
--- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame.
--- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame.
--- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps
-e_ShadowsCacheRequireManualUpdate = 2
-
-r_ClearGMEMGBuffer=1
-
--- Sort ligths since we have limited space in the shadowmap pool texture
-r_DeferredShadingSortLights = 3
-
---Use an optimized pixel format for the lighting rendertargets during the lighting pass.
-r_DeferredShadingLBuffersFmt = 2
\ No newline at end of file
diff --git a/Assets/Engine/Config/spec/android_high_nogmem.cfg b/Assets/Engine/Config/spec/android_high_nogmem.cfg
index ac718a57ee..fd7c0a349d 100644
--- a/Assets/Engine/Config/spec/android_high_nogmem.cfg
+++ b/Assets/Engine/Config/spec/android_high_nogmem.cfg
@@ -1,61 +1,8 @@
-sys_spec_Full=3
-
-- Cap frame rate at 30fps
sys_maxfps=30
r_vsync=0
--- Disabling gmem for this configuration
-r_EnableGMEMPath=0
-
--- Skip the native upscale as a second upscale already occurs
-r_SkipNativeUpscale=1
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
-sys_job_system_max_worker=2
sys_streaming_in_blocks=1
sys_streaming_memory_budget=512
-e_CheckOcclusion=1
-
-r_Fur=0
-az_Asset_EnableAsyncMeshLoading=0
-
-------------------------
--- Misc. memory buffers
-------------------------
-e_GeomCacheBufferSize=0
-e_CheckOcclusionQueueSize=512
-e_CheckOcclusionOutputQueueSize=1024
-
-------------------------
--- Animation
-------------------------
-ca_MemoryDefragPoolSize=33554432
-ca_StreamCHR=1
-
-------------------------
--- sys_spec_objectdetail
-------------------------
-e_Dissolve=2
-e_LodRatio=5
-e_ViewDistRatioDetail=19
-
-
-------------------------
--- sys_spec_shading
-------------------------
-r_VisAreaClipLightsPerPixel=0
-
--- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame.
--- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame.
--- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps
-e_ShadowsCacheRequireManualUpdate = 2
-
---Use an optimized pixel format for the lighting rendertargets during the lighting pass.
-r_DeferredShadingLBuffersFmt = 2
-
diff --git a/Assets/Engine/Config/spec/android_low.cfg b/Assets/Engine/Config/spec/android_low.cfg
index 6f2a876877..0ab8ebc37b 100644
--- a/Assets/Engine/Config/spec/android_low.cfg
+++ b/Assets/Engine/Config/spec/android_low.cfg
@@ -1,76 +1,7 @@
-sys_spec_Full=1
-
-- Cap frame rate at 30fps
sys_maxfps=30
r_vsync=0
--- Enable framebufferfetch(256bpp) or pls if applicable
-r_EnableGMEMPath=1
-
--- Skip the native upscale as a second upscale already occurs
-r_SkipNativeUpscale=1
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
-sys_job_system_max_worker=2
sys_streaming_in_blocks=1
sys_streaming_memory_budget=512
-
--- This allows the generation of reflections for the ocean water. Without it, the water looks really dark.
-e_recursion=0
-e_CheckOcclusion=1
-
-r_Fur=0
-
--- Water occlusion queries crash in some OpenGL ES 3.0 devices
-e_HwOcclusionCullingWater = 0
-az_Asset_EnableAsyncMeshLoading=0
-
-------------------------
--- Misc. memory buffers
-------------------------
-e_GeomCacheBufferSize=0
-e_CheckOcclusionQueueSize=512
-e_CheckOcclusionOutputQueueSize=1024
-
-------------------------
--- Animation
-------------------------
-ca_MemoryDefragPoolSize=33554432
-ca_StreamCHR=1
-
-------------------------
--- sys_spec_objectdetail
-------------------------
-e_Dissolve=2
-e_LodRatio=5
-e_ViewDistRatioDetail=19
-
-
-------------------------
--- sys_spec_shading
-------------------------
-r_VisAreaClipLightsPerPixel=0
-
-
-------------------------
--- sys_spec_textureresolution
-------------------------
-r_TexturesstreamingMinUsableMips=6
-
-
--- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame.
--- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame.
--- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps
-e_ShadowsCacheRequireManualUpdate = 2
-
--- Sort ligths since we have limited space in the shadowmap pool texture
-r_DeferredShadingSortLights = 3
-r_ClearGMEMGBuffer=1
-
---Use an optimized pixel format for the lighting rendertargets during the lighting pass.
-r_DeferredShadingLBuffersFmt = 2
\ No newline at end of file
diff --git a/Assets/Engine/Config/spec/android_medium.cfg b/Assets/Engine/Config/spec/android_medium.cfg
index f9d776efa7..0ab8ebc37b 100644
--- a/Assets/Engine/Config/spec/android_medium.cfg
+++ b/Assets/Engine/Config/spec/android_medium.cfg
@@ -1,81 +1,7 @@
-sys_spec_Full=2
-
-- Cap frame rate at 30fps
sys_maxfps=30
r_vsync=0
--- Enable framebufferfetch(256bpp) or pls if applicable
-r_EnableGMEMPath=1
-
--- Skip the native upscale as a second upscale already occurs
-r_SkipNativeUpscale=1
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
-sys_job_system_max_worker=2
sys_streaming_in_blocks=1
sys_streaming_memory_budget=512
-
--- This allows the generation of reflections for the ocean water. Without it, the water looks really dark.
-e_recursion=1
-e_CheckOcclusion=1
-
-r_Fur=0
-az_Asset_EnableAsyncMeshLoading=0
-
-------------------------
--- Misc. memory buffers
-------------------------
-e_GeomCacheBufferSize=0
-e_CheckOcclusionQueueSize=512
-e_CheckOcclusionOutputQueueSize=1024
-
-------------------------
--- Animation
-------------------------
-ca_MemoryDefragPoolSize=33554432
-ca_StreamCHR=1
-
-------------------------
--- sys_spec_objectdetail
-------------------------
-e_Dissolve=2
-e_LodRatio=5
-e_ViewDistRatioDetail=19
-e_ViewDistRatioVegetation=21
-
-
-------------------------
--- sys_spec_postprocessing
-------------------------
-r_HDRBloom=0
-r_SunShafts=0
-r_ToneMapExposureType=1
-r_ColorSpace=2
-
-------------------------
--- sys_spec_shading
-------------------------
-r_VisAreaClipLightsPerPixel=0
-
-------------------------
--- sys_spec_textureresolution
-------------------------
-r_TexturesstreamingMinUsableMips=7
-
--- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame.
--- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame.
--- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps
-e_ShadowsCacheRequireManualUpdate = 2
-
-r_ClearGMEMGBuffer=1
-
--- Sort ligths since we have limited space in the shadowmap pool texture
-r_DeferredShadingSortLights = 3
-
---Use an optimized pixel format for the lighting rendertargets during the lighting pass.
-r_DeferredShadingLBuffersFmt = 2
\ No newline at end of file
diff --git a/Assets/Engine/Config/spec/android_veryhigh.cfg b/Assets/Engine/Config/spec/android_veryhigh.cfg
index d4f8e9cd47..d58e319706 100644
--- a/Assets/Engine/Config/spec/android_veryhigh.cfg
+++ b/Assets/Engine/Config/spec/android_veryhigh.cfg
@@ -1,60 +1,5 @@
-sys_spec_Full=4
-
-- Cap frame rate at 30fps
sys_maxfps=30
r_vsync=0
-
--- Enable framebufferfetch(256bpp) or pls if applicable
-r_EnableGMEMPath=1
-
--- Skip the native upscale as a second upscale already occurs
-r_SkipNativeUpscale=1
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
-sys_job_system_max_worker=2
sys_streaming_in_blocks=1
-
sys_streaming_memory_budget=512
-
-e_CheckOcclusion=1
-
-r_Fur=0
-az_Asset_EnableAsyncMeshLoading=0
-
-------------------------
--- Misc. memory buffers
-------------------------
-e_GeomCacheBufferSize=0
-e_CheckOcclusionQueueSize=512
-e_CheckOcclusionOutputQueueSize=1024
-
-------------------------
--- Animation
-------------------------
-ca_MemoryDefragPoolSize=33554432
-ca_StreamCHR=1
-
-------------------------
--- sys_spec_objectdetail
-------------------------
-e_Dissolve=2
-e_LodRatio=5
-e_ViewDistRatioDetail=19
-
-
-------------------------
--- sys_spec_shading
-------------------------
-r_VisAreaClipLightsPerPixel=0
-
-r_ClearGMEMGBuffer=1
-
--- Sort ligths since we have limited space in the shadowmap pool texture
-r_DeferredShadingSortLights = 3
-
---Use an optimized pixel format for the lighting rendertargets during the lighting pass.
-r_DeferredShadingLBuffersFmt = 2
\ No newline at end of file
diff --git a/Assets/Engine/Config/spec/ios_high.cfg b/Assets/Engine/Config/spec/ios_high.cfg
index 67fa99ca04..d0cf5b3bc5 100644
--- a/Assets/Engine/Config/spec/ios_high.cfg
+++ b/Assets/Engine/Config/spec/ios_high.cfg
@@ -1,100 +1,10 @@
-sys_spec_Full=3
-
-- Cap frame rate at 30fps
sys_maxfps=30
r_vsync=1
--- Enable framebufferfetch or pls if applicable
-r_EnableGMEMPath=1
-
--- Skip the native upscale as a second upscale occurs on Metal Present
-r_SkipNativeUpscale=1
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
-
-------------------------
--- Job System
-------------------------
-sys_job_system_enable=0
-sys_job_system_max_worker=1
-
------------------------
-- Streaming
------------------------
sys_streaming_in_blocks=1
sys_streaming_memory_budget=512
-------------------------
--- General Rendering
-------------------------
-r_Flush=0
--- Enabling this will clear the GMEM buffer before the z-pass
-r_ClearGMEMGBuffer=2
-r_Fur=0
-
-------------------------
--- VisArea / Portals
-------------------------
-e_PortalsBlend=0
-r_GMEMVisAreasBlendWeight=0.5
-
-------------------------
--- Misc. memory buffers
-------------------------
-e_AutoPrecacheCgf=2
-e_AutoPrecacheTerrainAndProcVeget=1
-e_GeomCacheBufferSize=0
-e_CheckOcclusionQueueSize=512
-e_CheckOcclusionOutputQueueSize=2048
-
-------------------------
--- Animation
-------------------------
-ca_MemoryDefragPoolSize=32
-ca_StreamCHR=1
-
-------------------------
--- sys_spec_water
-------------------------
-e_WaterOcean=2
-e_WaterVolumes=2
-e_WaterOceanBottom=0
-
-------------------------
--- batching
-------------------------
-r_Batching = 1
-r_BatchType = 0
-
-------------------------
--- geom instancing
-------------------------
-r_GeomInstancing=1
-r_GeomInstancingThreshold=5
-
-------------------------
--- Upscaling
-------------------------
---0 point, 1 bilinear, 2 bicubic, 3 lanczos
-r_UpscalingQuality=1
-
-------------------------
--- Geometry Cache
-------------------------
-e_GeomCaches=0
-
-
--- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame.
--- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame.
--- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps
-e_ShadowsCacheRequireManualUpdate = 2
-
--- Sort ligths since we have limited space in the shadowmap pool texture
-r_DeferredShadingSortLights = 3
-
---Use an optimized pixel format for the lighting rendertargets during the lighting pass.
-r_DeferredShadingLBuffersFmt = 2
\ No newline at end of file
diff --git a/Assets/Engine/Config/spec/ios_low.cfg b/Assets/Engine/Config/spec/ios_low.cfg
index 7870d65bd5..d0cf5b3bc5 100644
--- a/Assets/Engine/Config/spec/ios_low.cfg
+++ b/Assets/Engine/Config/spec/ios_low.cfg
@@ -1,103 +1,10 @@
-sys_spec_Full=1
-
-- Cap frame rate at 30fps
sys_maxfps=30
r_vsync=1
--- Enable framebufferfetch or pls if applicable
-r_EnableGMEMPath=1
-
--- Skip the native upscale as a second upscale occurs on Metal Present
-r_SkipNativeUpscale=1
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
-
-------------------------
--- Job System
-------------------------
-sys_job_system_enable=0
-sys_job_system_max_worker=1
-
------------------------
-- Streaming
------------------------
sys_streaming_in_blocks=1
sys_streaming_memory_budget=512
-------------------------
--- General Rendering
-------------------------
-r_Flush=0
--- Enabling this will clear the GMEM buffer before the z-pass
-r_ClearGMEMGBuffer=2
-r_Fur=0
-
-------------------------
--- VisArea / Portals
-------------------------
-e_PortalsBlend=0
-r_GMEMVisAreasBlendWeight=0.5
-
-------------------------
--- Misc. memory buffers
-------------------------
-e_AutoPrecacheCgf=2
-e_AutoPrecacheTerrainAndProcVeget=1
-e_GeomCacheBufferSize=0
-e_CheckOcclusionQueueSize=512
-e_CheckOcclusionOutputQueueSize=1024
-
-------------------------
--- Animation
-------------------------
-ca_MemoryDefragPoolSize=32
-ca_StreamCHR=1
-
-------------------------
--- sys_spec_water
-------------------------
-e_WaterOcean=2
-e_WaterVolumes=2
-e_WaterOceanBottom=0
-
-
-------------------------
--- batching
-------------------------
-r_Batching = 1
-r_BatchType = 0
-
-------------------------
--- geom instancing
-------------------------
-r_GeomInstancing=1
-r_GeomInstancingThreshold=5
-
-------------------------
--- Upscaling
-------------------------
---0 point, 1 bilinear, 2 bicubic, 3 lanczos
-r_UpscalingQuality=1
-
-------------------------
--- Geometry Cache
-------------------------
-e_GeomCaches=0
-
-
-
-
--- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame.
--- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame.
--- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps
-e_ShadowsCacheRequireManualUpdate = 2
-
--- Sort ligths since we have limited space in the shadowmap pool texture
-r_DeferredShadingSortLights = 3
-
---Use an optimized pixel format for the lighting rendertargets during the lighting pass.
-r_DeferredShadingLBuffersFmt = 2
\ No newline at end of file
diff --git a/Assets/Engine/Config/spec/ios_medium.cfg b/Assets/Engine/Config/spec/ios_medium.cfg
index 2eaecdef16..d0cf5b3bc5 100644
--- a/Assets/Engine/Config/spec/ios_medium.cfg
+++ b/Assets/Engine/Config/spec/ios_medium.cfg
@@ -1,101 +1,10 @@
-sys_spec_Full=2
-
-- Cap frame rate at 30fps
sys_maxfps=30
r_vsync=1
--- Enable framebufferfetch or pls if applicable
-r_EnableGMEMPath=1
-
--- Skip the native upscale as a second upscale occurs on Metal Present
-r_SkipNativeUpscale=1
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
-
-------------------------
--- Job System
-------------------------
-sys_job_system_enable=0
-sys_job_system_max_worker=1
-
------------------------
-- Streaming
------------------------
sys_streaming_in_blocks=1
sys_streaming_memory_budget=512
-------------------------
--- General Rendering
-------------------------
-r_Flush=0
--- Enabling this will clear the GMEM buffer before the z-pass
-r_ClearGMEMGBuffer=2
-r_Fur=0
-
-------------------------
--- VisArea / Portals
-------------------------
-e_PortalsBlend=0
-r_GMEMVisAreasBlendWeight=0.5
-
-------------------------
--- Misc. memory buffers
-------------------------
-e_AutoPrecacheCgf=2
-e_AutoPrecacheTerrainAndProcVeget=1
-e_GeomCacheBufferSize=0
-e_CheckOcclusionQueueSize=512
-e_CheckOcclusionOutputQueueSize=1024
-
-------------------------
--- Animation
-------------------------
-ca_MemoryDefragPoolSize=32
-ca_StreamCHR=1
-
-------------------------
--- sys_spec_water
-------------------------
-e_WaterOcean=2
-e_WaterVolumes=2
-e_WaterOceanBottom=0
-
-
-------------------------
--- batching
-------------------------
-r_Batching = 1
-r_BatchType = 0
-
-------------------------
--- geom instancing
-------------------------
-r_GeomInstancing=1
-r_GeomInstancingThreshold=5
-
-------------------------
--- Upscaling
-------------------------
---0 point, 1 bilinear, 2 bicubic, 3 lanczos
-r_UpscalingQuality=1
-
-------------------------
--- Geometry Cache
-------------------------
-e_GeomCaches=0
-
-
--- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame.
--- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame.
--- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps
-e_ShadowsCacheRequireManualUpdate = 2
-
--- Sort ligths since we have limited space in the shadowmap pool texture
-r_DeferredShadingSortLights = 3
-
---Use an optimized pixel format for the lighting rendertargets during the lighting pass.
-r_DeferredShadingLBuffersFmt = 2
\ No newline at end of file
diff --git a/Assets/Engine/Config/spec/ios_veryhigh.cfg b/Assets/Engine/Config/spec/ios_veryhigh.cfg
index 53937a77bf..d0cf5b3bc5 100644
--- a/Assets/Engine/Config/spec/ios_veryhigh.cfg
+++ b/Assets/Engine/Config/spec/ios_veryhigh.cfg
@@ -1,102 +1,10 @@
-sys_spec_Full=4
-
-- Cap frame rate at 30fps
sys_maxfps=30
r_vsync=1
--- Enable framebufferfetch or pls if applicable
-r_EnableGMEMPath=1
-
--- Skip the native upscale as a second upscale occurs on Metal Present
-r_SkipNativeUpscale=1
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
-
-------------------------
--- Job System
-------------------------
-sys_job_system_enable=0
-sys_job_system_max_worker=1
-
------------------------
-- Streaming
------------------------
sys_streaming_in_blocks=1
sys_streaming_memory_budget=512
-------------------------
--- General Rendering
-------------------------
-r_Flush=0
--- Enabling this will clear the GMEM buffer before the z-pass
-r_ClearGMEMGBuffer=2
-r_Fur=0
-
-------------------------
--- VisArea / Portals
-------------------------
-e_PortalsBlend=0
-r_GMEMVisAreasBlendWeight=0.5
-
-------------------------
--- Misc. memory buffers
-------------------------
-e_AutoPrecacheCgf=2
-e_AutoPrecacheTerrainAndProcVeget=1
-e_GeomCacheBufferSize=0
-e_CheckOcclusionQueueSize=512
-e_CheckOcclusionOutputQueueSize=2048
-
-------------------------
--- Animation
-------------------------
-ca_MemoryDefragPoolSize=32
-ca_StreamCHR=1
-
-------------------------
--- sys_spec_water
-------------------------
-e_WaterOcean=2
-e_WaterVolumes=2
-e_WaterOceanBottom=0
-
-
-------------------------
--- batching
-------------------------
-r_Batching = 1
-r_BatchType = 0
-
-------------------------
--- geom instancing
-------------------------
-r_GeomInstancing=1
-r_GeomInstancingThreshold=5
-
-------------------------
--- Upscaling
-------------------------
---0 point, 1 bilinear, 2 bicubic, 3 lanczos
-r_UpscalingQuality=1
-
-------------------------
--- Geometry Cache
-------------------------
-e_GeomCaches=0
-
-
-
--- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame.
--- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame.
--- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps
-e_ShadowsCacheRequireManualUpdate = 2
-
--- Sort ligths since we have limited space in the shadowmap pool texture
-r_DeferredShadingSortLights = 3
-
---Use an optimized pixel format for the lighting rendertargets during the lighting pass.
-r_DeferredShadingLBuffersFmt = 2
\ No newline at end of file
diff --git a/Assets/Engine/Config/spec/osx_metal_high.cfg b/Assets/Engine/Config/spec/osx_metal_high.cfg
deleted file mode 100644
index 8689e23c51..0000000000
--- a/Assets/Engine/Config/spec/osx_metal_high.cfg
+++ /dev/null
@@ -1,38 +0,0 @@
-
-sys_spec_Full=7
-r_ShadersMETAL=1
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
--- Skip the native upscale as a second upscale occurs on Metal Present
-r_SkipNativeUpscale=1
-
-------------------------
--- sys_spec_postprocessing
-------------------------
-r_SunShafts=1
-
-------------------------
--- sys_spec_shading
-------------------------
-r_DeferredShadingTiled=0
-r_RefractionPartialResolves=0
-e_GI = 0
-
-
-r_Fur=2
-
-
-------------------------
--- Upscaling
-------------------------
---0 point, 1 bilinear, 2 bicubic, 3 lanczos
-r_UpscalingQuality=1
-
--- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame.
--- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame.
--- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps
-e_ShadowsCacheRequireManualUpdate = 2
diff --git a/Assets/Engine/Config/spec/osx_metal_low.cfg b/Assets/Engine/Config/spec/osx_metal_low.cfg
deleted file mode 100644
index a3084d48c5..0000000000
--- a/Assets/Engine/Config/spec/osx_metal_low.cfg
+++ /dev/null
@@ -1,37 +0,0 @@
-
-sys_spec_Full=5
-r_ShadersMETAL=1
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
--- Skip the native upscale as a second upscale occurs on Metal Present
-r_SkipNativeUpscale=1
-
-------------------------
--- sys_spec_postprocessing
-------------------------
-r_SunShafts=1
-
-------------------------
--- sys_spec_shading
-------------------------
-r_DeferredShadingTiled=0
-r_RefractionPartialResolves=0
-e_GI=0
-
-r_Fur=2
-
-
-------------------------
--- Upscaling
-------------------------
---0 point, 1 bilinear, 2 bicubic, 3 lanczos
-r_UpscalingQuality=1
-
--- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame.
--- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame.
--- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps
-e_ShadowsCacheRequireManualUpdate = 2
diff --git a/Assets/Engine/Config/spec/osx_metal_medium.cfg b/Assets/Engine/Config/spec/osx_metal_medium.cfg
deleted file mode 100644
index 6477bbb217..0000000000
--- a/Assets/Engine/Config/spec/osx_metal_medium.cfg
+++ /dev/null
@@ -1,37 +0,0 @@
-
-sys_spec_Full=6
-r_ShadersMETAL=1
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
--- Skip the native upscale as a second upscale occurs on Metal Present
-r_SkipNativeUpscale=1
-
-------------------------
--- sys_spec_postprocessing
-------------------------
-r_SunShafts=1
-
-------------------------
--- sys_spec_shading
-------------------------
-r_DeferredShadingTiled=0
-r_RefractionPartialResolves=0
-e_GI = 0
-
-r_Fur=2
-
-
-------------------------
--- Upscaling
-------------------------
---0 point, 1 bilinear, 2 bicubic, 3 lanczos
-r_UpscalingQuality=1
-
--- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame.
--- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame.
--- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps
-e_ShadowsCacheRequireManualUpdate = 2
diff --git a/Assets/Engine/Config/spec/osx_metal_veryhigh.cfg b/Assets/Engine/Config/spec/osx_metal_veryhigh.cfg
deleted file mode 100644
index 899c198f31..0000000000
--- a/Assets/Engine/Config/spec/osx_metal_veryhigh.cfg
+++ /dev/null
@@ -1,37 +0,0 @@
-
-sys_spec_Full=8
-r_ShadersMETAL=1
-
--- Default of 3 allocates all shaders (potentially >150 MB)
--- 1 is most memory efficient but definitely causes hitches when converting HLSL
--- shaders. Recommend 1 during dev, and 3 with optimized caches for release.
-r_ShadersPreactivate=1
-
--- Skip the native upscale as a second upscale occurs on Metal Present
-r_SkipNativeUpscale=1
-
-------------------------
--- sys_spec_postprocessing
-------------------------
-r_SunShafts=1
-
-------------------------
--- sys_spec_shading
-------------------------
-r_DeferredShadingTiled=0
-r_RefractionPartialResolves=0
-e_GI = 0
-
-r_Fur=2
-
-
-------------------------
--- Upscaling
-------------------------
---0 point, 1 bilinear, 2 bicubic, 3 lanczos
-r_UpscalingQuality=1
-
--- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame.
--- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame.
--- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps
-e_ShadowsCacheRequireManualUpdate = 2
diff --git a/Assets/Engine/Config/spec/pc_high.cfg b/Assets/Engine/Config/spec/pc_high.cfg
index a62ed25a6a..e69de29bb2 100644
--- a/Assets/Engine/Config/spec/pc_high.cfg
+++ b/Assets/Engine/Config/spec/pc_high.cfg
@@ -1 +0,0 @@
-sys_spec_Full = 7
\ No newline at end of file
diff --git a/Assets/Engine/Config/spec/pc_low.cfg b/Assets/Engine/Config/spec/pc_low.cfg
index 068446e151..e69de29bb2 100644
--- a/Assets/Engine/Config/spec/pc_low.cfg
+++ b/Assets/Engine/Config/spec/pc_low.cfg
@@ -1 +0,0 @@
-sys_spec_Full = 5
diff --git a/Assets/Engine/Config/spec/pc_medium.cfg b/Assets/Engine/Config/spec/pc_medium.cfg
index 0d08b956b4..e69de29bb2 100644
--- a/Assets/Engine/Config/spec/pc_medium.cfg
+++ b/Assets/Engine/Config/spec/pc_medium.cfg
@@ -1 +0,0 @@
-sys_spec_Full = 6
\ No newline at end of file
diff --git a/Assets/Engine/Config/spec/pc_veryhigh.cfg b/Assets/Engine/Config/spec/pc_veryhigh.cfg
index 33959937e8..e69de29bb2 100644
--- a/Assets/Engine/Config/spec/pc_veryhigh.cfg
+++ b/Assets/Engine/Config/spec/pc_veryhigh.cfg
@@ -1 +0,0 @@
-sys_spec_Full = 8
diff --git a/Assets/Engine/Config/statoscope.cfg b/Assets/Engine/Config/statoscope.cfg
index d1d18c813c..ed2089bd67 100644
--- a/Assets/Engine/Config/statoscope.cfg
+++ b/Assets/Engine/Config/statoscope.cfg
@@ -1,12 +1,3 @@
profile=-1
-profile_allthreads=1
-i_forcefeedback=0
-g_godmode=1
log_verbosity=-1
sys_pakLogInvalidFileAccess=1
-e_StatoscopeDataGroups=fgmrtudlipny
-e_StatoscopeFilenameUseBuildInfo=0
-e_StatoscopeFilenameUseMap=1
-e_StatoscopeMinFuncLengthMs=0.1
-e_StatoscopeMaxNumFuncsPerFrame=60
-e_StatoscopeScreenshotCapturePeriod=5
diff --git a/Assets/Engine/Config/vr.cfg b/Assets/Engine/Config/vr.cfg
index 989f55f345..80d4b7ce81 100644
--- a/Assets/Engine/Config/vr.cfg
+++ b/Assets/Engine/Config/vr.cfg
@@ -3,39 +3,13 @@
-----------------------------------------------
r_width = 960
r_height = 1080
-r_backbufferWidth = 1920
-r_backbufferHeight = 1080
-
-------------------------------------------
-- Set the system Spec (Medium)
-------------------------------------------
sys_spec = 2
-
--------------------------------------------
--- HMD related
--------------------------------------------
-r_overrideDXGIoutput = 0
-r_stereodevice = 100
-r_stereomode = 1
-r_stereooutput = 7
-r_minimizeLatency = 1
-hmd_low_persistence = 1
-r_stereoScaleCoefficient = 1
-
-
-------------------------------------------
-- Set some video optimisations
-------------------------------------------
r_vsync = 0
-r_MotionBlur = 0
-r_ssdoHalfRes = 3
-r_Refraction = 0
-r_DeferredShadingTiled = 0
-r_CBufferUseNativeDepth = 0
-
--------------------------------------------
--- Hide the hud
--------------------------------------------
---hud_hide = 1
diff --git a/Assets/Engine/SeedAssetList.seed b/Assets/Engine/SeedAssetList.seed
index 579fd3c444..aafbffbe8f 100644
--- a/Assets/Engine/SeedAssetList.seed
+++ b/Assets/Engine/SeedAssetList.seed
@@ -48,22 +48,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -432,110 +416,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -616,38 +496,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py
index e4a77ca4ec..3403c938a8 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py
@@ -23,20 +23,20 @@ TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "tests")
class TestAtomEditorComponentsMain(object):
"""Holds tests for Atom components."""
+ @pytest.mark.test_case_id("C32078118") # Decal
+ @pytest.mark.test_case_id("C32078119") # DepthOfField
+ @pytest.mark.test_case_id("C32078120") # Directional Light
+ @pytest.mark.test_case_id("C32078121") # Exposure Control
+ @pytest.mark.test_case_id("C32078115") # Global Skylight (IBL)
+ @pytest.mark.test_case_id("C32078125") # Physical Sky
+ @pytest.mark.test_case_id("C32078127") # PostFX Layer
+ @pytest.mark.test_case_id("C32078131") # PostFX Radius Weight Modifier
+ @pytest.mark.test_case_id("C32078117") # Light
+ @pytest.mark.test_case_id("C36525660") # Display Mapper
def test_AtomEditorComponents_AddedToEntity(self, request, editor, level, workspace, project, launcher_platform):
"""
Please review the hydra script run by this test for more specific test info.
- Tests the following Atom components and verifies all "expected_lines" appear in Editor.log:
- 1. Display Mapper
- 2. Light
- 3. PostFX Radius Weight Modifier
- 4. PostFX Layer
- 5. Physical Sky
- 6. Global Skylight (IBL)
- 7. Exposure Control
- 8. Directional Light
- 9. DepthOfField
- 10. Decal
+ Tests the Atom components & verifies all "expected_lines" appear in Editor.log
"""
cfg_args = [level]
@@ -69,6 +69,18 @@ class TestAtomEditorComponentsMain(object):
"DepthOfField_test: Entity deleted: True",
"DepthOfField_test: UNDO entity deletion works: True",
"DepthOfField_test: REDO entity deletion works: True",
+ # Directional Light Component
+ "Directional Light Entity successfully created",
+ "Directional Light_test: Component added to the entity: True",
+ "Directional Light_test: Component removed after UNDO: True",
+ "Directional Light_test: Component added after REDO: True",
+ "Directional Light_test: Entered game mode: True",
+ "Directional Light_test: Exit game mode: True",
+ "Directional Light_test: Entity is hidden: True",
+ "Directional Light_test: Entity is shown: True",
+ "Directional Light_test: Entity deleted: True",
+ "Directional Light_test: UNDO entity deletion works: True",
+ "Directional Light_test: REDO entity deletion works: True",
# Exposure Control Component
"Exposure Control Entity successfully created",
"Exposure Control_test: Component added to the entity: True",
@@ -180,6 +192,7 @@ class TestAtomEditorComponentsMain(object):
cfg_args=cfg_args,
)
+ @pytest.mark.test_case_id("C34525095")
def test_AtomEditorComponents_LightComponent(
self, request, editor, workspace, project, launcher_platform, level):
"""
@@ -266,6 +279,15 @@ class TestMaterialEditorBasicTests(object):
request.addfinalizer(teardown)
@pytest.mark.parametrize("exe_file_name", ["MaterialEditor"])
+ @pytest.mark.test_case_id("C34448113") # Creating a New Asset.
+ @pytest.mark.test_case_id("C34448114") # Opening an Existing Asset.
+ @pytest.mark.test_case_id("C34448115") # Closing Selected Material.
+ @pytest.mark.test_case_id("C34448116") # Closing All Materials.
+ @pytest.mark.test_case_id("C34448117") # Closing all but Selected Material.
+ @pytest.mark.test_case_id("C34448118") # Saving Material.
+ @pytest.mark.test_case_id("C34448119") # Saving as a New Material.
+ @pytest.mark.test_case_id("C34448120") # Saving as a Child Material.
+ @pytest.mark.test_case_id("C34448121") # Saving all Open Materials.
def test_MaterialEditorBasicTests(
self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name):
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py
index 220623af8b..74b064a555 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py
@@ -73,6 +73,7 @@ def create_screenshots_archive(screenshot_path):
class TestAllComponentsIndepthTests(object):
@pytest.mark.parametrize("screenshot_name", ["AtomBasicLevelSetup.ppm"])
+ @pytest.mark.test_case_id("C34603773")
def test_BasicLevelSetup_SetsUpLevel(
self, request, editor, workspace, project, launcher_platform, level, screenshot_name):
"""
@@ -115,6 +116,7 @@ class TestAllComponentsIndepthTests(object):
create_screenshots_archive(screenshot_directory)
+ @pytest.mark.test_case_id("C34525095")
def test_LightComponent_ScreenshotMatchesGoldenImage(
self, request, editor, workspace, project, launcher_platform, level):
"""
@@ -225,6 +227,8 @@ class TestMaterialEditor(object):
pytest.param("-rhi=Vulkan", ["Registering vulkan RHI"])
])
@pytest.mark.parametrize("exe_file_name", ["MaterialEditor"])
+ @pytest.mark.test_case_id("C30973986") # Material Editor Launching in Dx12
+ @pytest.mark.test_case_id("C30973987") # Material Editor Launching in Vulkan
def test_MaterialEditorLaunch_AllRHIOptionsSucceed(
self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name, cfg_args,
expected_lines):
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU_Optimized.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU_Optimized.py
index ef572d6e5c..568768e12e 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU_Optimized.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU_Optimized.py
@@ -23,6 +23,7 @@ class TestAutomation(EditorTestSuite):
# Remove -autotest_mode from global_extra_cmdline_args since we need rendering for these tests.
global_extra_cmdline_args = ["-BatchMode"] # Default is ["-BatchMode", "-autotest_mode"]
+ @pytest.mark.test_case_id("C34603773")
class AtomGPU_BasicLevelSetup_SetsUpLevel(EditorSharedTest):
use_null_renderer = False # Default is True
screenshot_name = "AtomBasicLevelSetup.ppm"
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py
index 79caf26784..58e5d00ff2 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py
@@ -30,6 +30,7 @@ class TestAtomEditorComponentsSandbox(object):
class TestAtomEditorComponentsMain(object):
"""Holds tests for Atom components."""
+ @pytest.mark.test_case_id("C32078128")
def test_AtomEditorComponents_ReflectionProbeAddedToEntity(
self, request, editor, level, workspace, project, launcher_platform):
"""
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py
index 821e0acfdb..11832f8846 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py
@@ -113,7 +113,6 @@ def create_basic_atom_level(level_name):
general.close_pane("Error Log")
general.idle_wait(1.0)
general.run_console("r_displayInfo=0")
- general.run_console("r_antialiasingmode=0")
general.idle_wait(1.0)
# Delete all existing entities & create default_level entity
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py
index 0ba7038c47..4c98bcd130 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py
@@ -160,6 +160,7 @@ def AtomEditorComponents_postfx_shape_weight_AddedToEntity():
# 9. Undo to remove each added shape and verify PostFX Shape Weight Modifier is not enabled.
general.undo()
+ TestHelper.wait_for_condition(lambda: not postfx_shape_weight_entity.has_component(shape), 1.0)
Report.result(Tests.postfx_shape_weight_disabled, not postfx_shape_weight_component.is_enabled())
# 10. Verify PostFx Shape Weight Modifier component is enabled by adding Spline and Tube Shape component.
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py
index 92199bf196..fbd9f3459a 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py
@@ -66,7 +66,6 @@ def run():
general.close_pane("Error Log")
general.idle_wait(1.0)
general.run_console("r_displayInfo=0")
- general.run_console("r_antialiasingmode=0")
general.idle_wait(1.0)
return True
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py
index ac28e67fa1..93e78a7c0a 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py
@@ -82,7 +82,6 @@ def run():
general.close_pane("Error Log")
general.idle_wait(1.0)
general.run_console("r_displayInfo=0")
- general.run_console("r_antialiasingmode=0")
general.idle_wait(1.0)
return True
diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py
index ef3048d8d4..1b094b1cfa 100644
--- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py
+++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py
@@ -149,7 +149,6 @@ class TestHelper:
general.idle_wait(1.0)
general.idle_wait(1.0)
general.run_console("r_displayInfo=0")
- general.run_console("r_antialiasingmode=0")
general.idle_wait(1.0)
diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py
index 0e8d7ea255..1209cb6caf 100644
--- a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py
+++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py
@@ -52,9 +52,6 @@ def Joints_BallLeadFollowerCollide():
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
- import azlmbr.legacy.general as general
- import azlmbr.bus
-
from JointsHelper import JointEntityCollisionAware
# Helper Entity class - self.collided flag is set when instance receives collision event.
@@ -75,17 +72,12 @@ def Joints_BallLeadFollowerCollide():
lead = Entity("lead")
follower = Entity("follower")
- # 4) Wait for several seconds
- general.idle_wait(2.0) # wait for lead and follower to move
+ # 4) Wait for collision between lead and follower or timeout
+ Report.critical_result(Tests.check_collision_happened, helper.wait_for_condition(lambda: lead.collided and follower.collided, 10.0))
- # 5) Check to see if lead and follower behaved as expected
- Report.critical_result(Tests.check_collision_happened, lead.collided and follower.collided)
-
- # 6) Exit Game Mode
+ # 5) Exit Game Mode
helper.exit_game_mode(Tests.exit_game_mode)
-
-
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(Joints_BallLeadFollowerCollide)
diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py
index 0870a807fc..0b3f88b4f6 100644
--- a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py
+++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py
@@ -52,11 +52,13 @@ def Joints_HingeNoLimitsConstrained():
"""
import os
import sys
+ import math
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
import azlmbr.legacy.general as general
import azlmbr.bus
+ import azlmbr.math as azmath
import JointsHelper
from JointsHelper import JointEntity
@@ -84,28 +86,65 @@ def Joints_HingeNoLimitsConstrained():
Report.info_vector3(lead.position, "lead initial position:")
Report.info_vector3(follower.position, "follower initial position:")
leadInitialPosition = lead.position
- followerInitialPosition = follower.position
- # 4) Wait for several seconds
- general.idle_wait(4.0) # wait for lead and follower to move
+ # 4) Wait for the follower to move above and over the lead or Timeout
+ normalizedStartPos = JointsHelper.getRelativeVector(lead.position, follower.position)
+ normalizedStartPos = normalizedStartPos.GetNormalizedSafe()
+
+ class WaitCondition:
+ ANGLE_CHECKPOINT_1 = math.radians(90)
+ ANGLE_CHECKPOINT_2 = math.radians(200)
+
+ angleAchieved = 0.0
+ followerMovedAbove90Deg = False #this is expected to be true to pass the test
+ followerMovedAbove200Deg = False #this is expected to be true to pass the test
+
+ jointNormal = azmath.Vector3(0.0, -1.0, 0.0) # the joint rotates around the y axis
+ def checkConditionMet(self):
+ #calculate the current follower-lead vector
+ normalVec = JointsHelper.getRelativeVector(lead.position, follower.position)
+ normalVec = normalVec.GetNormalizedSafe()
+
+ #triple product and get the angle
+ tripleProduct = normalizedStartPos.dot(normalVec.cross(self.jointNormal))
+ currentAngle = math.acos(normalizedStartPos.Dot(normalVec))
+ if tripleProduct < 0:
+ currentAngle = (2*math.pi) - currentAngle
+
+ #if the angle is now less then last time, it is no longer rising, so end the test.
+ if currentAngle < self.angleAchieved:
+ return True
+
+ #once we're passed the final check point, end the test
+ if currentAngle > self.ANGLE_CHECKPOINT_2:
+ self.followerMovedAbove200Deg = True
+ return True
+
+ self.angleAchieved = currentAngle
+ self.followerMovedAbove90Deg = currentAngle > self.ANGLE_CHECKPOINT_1
+ return False
+
+ def isFollowerPositionCorrect(self):
+ return self.followerMovedAbove90Deg and self.followerMovedAbove200Deg
+
+ waitCondition = WaitCondition()
+
+ MAX_WAIT_TIME = 10.0 #seconds
+ conditionMet = helper.wait_for_condition(lambda: waitCondition.checkConditionMet(), MAX_WAIT_TIME)
# 5) Check to see if lead and follower behaved as expected
- Report.info_vector3(lead.position, "lead position after 1 second:")
- Report.info_vector3(follower.position, "follower position after 1 second:")
+ Report.info_vector3(lead.position, "lead position after test run:")
+ Report.info_vector3(follower.position, "follower position after test run:")
leadPositionDelta = lead.position.Subtract(leadInitialPosition)
leadRemainedStill = JointsHelper.vector3SmallerThanScalar(leadPositionDelta, FLOAT_EPSILON)
Report.critical_result(Tests.check_lead_position, leadRemainedStill)
- followerSwingedOverLead = (follower.position.x < leadInitialPosition.x and
- follower.position.z > leadInitialPosition.z)
- Report.critical_result(Tests.check_follower_position, followerSwingedOverLead)
+ Report.critical_result(Tests.check_follower_position, conditionMet and waitCondition.isFollowerPositionCorrect())
# 6) Exit Game Mode
helper.exit_game_mode(Tests.exit_game_mode)
-
-
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(Joints_HingeNoLimitsConstrained)
diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/screenshot_utils.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/screenshot_utils.py
index 49cf17855f..22fa3aca0d 100755
--- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/screenshot_utils.py
+++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/screenshot_utils.py
@@ -187,7 +187,3 @@ def prepare_for_screenshot_compare(remote_console_instance):
"""
wait_for(lambda: _retry_command(remote_console_instance, 'r_displayinfo 0',
'$3r_DisplayInfo = $60 $5[DUMPTODISK, RESTRICTEDMODE]$4'))
- wait_for(lambda: _retry_command(remote_console_instance, 'r_antialiasingmode 0',
- '$3r_AntialiasingMode = $60 $5[]$4'))
- wait_for(lambda: _retry_command(remote_console_instance, 'e_WaterOcean 0',
- '$3e_WaterOcean = $60 $5[]$4'))
diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py
new file mode 100644
index 0000000000..39cacf9af5
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py
@@ -0,0 +1,101 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+
+class Tests:
+ load_level = (
+ "Level loaded successfully",
+ "Failed to load the level"
+ )
+ create_entity = (
+ "Parent entity created successfully",
+ "Failed to create a parent entity"
+ )
+ set_entity_name = (
+ "Entity name set successfully",
+ "Failed to set entity name"
+ )
+ delete_entity = (
+ "Parent Entity deleted successfully",
+ "Failed to delete parent entity"
+ )
+ create_child_entity = (
+ "Child entity created successfully",
+ "Failed to create a child entity"
+ )
+ delete_child_entity = (
+ "Child entity deleted successfully",
+ "Failed to delete child entity"
+ )
+ add_mesh_component = (
+ "Mesh component added successfully",
+ "Failed to add mesh component"
+ )
+ found_component_typeId = (
+ "Found component typeId",
+ "Unable to find component TypeId"
+ )
+ remove_mesh_component = (
+ "Mesh component removed successfully",
+ "Failed to remove mesh component"
+ )
+
+
+def BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD():
+ """
+ Performing basic test in editor
+ 01. Load exiting level
+ 02. create parent entity and set name
+ 03. create child entity and set a name
+ 04. delete child entity
+ 05. add mesh component to parent entity
+ 06. delete parent entity
+ """
+
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.editor_entity_utils import EditorEntity
+
+ import azlmbr.bus as bus
+ import azlmbr.editor as editor
+ import azlmbr.entity as entity
+ import azlmbr.legacy.general as general
+ import azlmbr.object
+
+ # 01. load an existing level
+ test_level = 'Simple'
+ general.open_level_no_prompt(test_level)
+ Report.result(Tests.load_level, general.get_current_level_name() == test_level)
+
+ # 02. create parent entity and set name
+ # Delete any exiting entity and Create a new Entity at the root level
+ search_filter = azlmbr.entity.SearchFilter()
+ all_entities = entity.SearchBus(azlmbr.bus.Broadcast, "SearchEntities", search_filter)
+ editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntities", all_entities)
+ parent_entity = EditorEntity.create_editor_entity("Parent_1")
+ Report.result(Tests.create_entity, parent_entity.exists())
+
+ # 03. Create child Entity to above created parent entity and set a name
+ child_1_entity = EditorEntity.create_editor_entity("Child_1", parent_entity.id )
+ Report.result(Tests.create_child_entity, child_1_entity.exists())
+
+ # 04. delete_Child_entity
+ child_1_entity.delete()
+ Report.result(Tests.delete_child_entity, not child_1_entity.exists())
+
+ # 05. add mesh component to parent entity
+ parent_entity.add_component("Mesh")
+ Report.result(Tests.add_mesh_component, parent_entity.has_component("Mesh"))
+
+ # 06. delete parent entity
+ parent_entity.delete()
+ Report.result(Tests.delete_entity, not parent_entity.exists())
+
+
+if __name__ == "__main__":
+ from editor_python_test_tools.utils import Report
+
+ Report.start_test(BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD)
diff --git a/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py
index 9c0b99daff..afc52f962d 100644
--- a/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py
+++ b/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py
@@ -73,3 +73,7 @@ class TestAutomationAutoTestMode(EditorTestSuite):
@pytest.mark.skip(reason="Times out due to dialogs failing to dismiss: LYN-4208")
class test_Menus_FileMenuOptions_Work(EditorSharedTest):
from .EditorScripts import Menus_FileMenuOptions as test_module
+
+
+ class test_BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD(EditorSharedTest):
+ from .EditorScripts import BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD as test_module
diff --git a/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly b/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly
index 86dd941423..9babf84ba4 100644
--- a/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly
+++ b/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:817bd8dd22e185136418b60fba5b3552993687515d3d5ae96791f2c3be907b92
-size 7233
+oid sha256:60276c07b45a734e4f71d695278167ea61e884f8b513906168c9642078ad5954
+size 6045
diff --git a/Code/Editor/Controls/FolderTreeCtrl.cpp b/Code/Editor/Controls/FolderTreeCtrl.cpp
index 4088ab976f..1464580ffc 100644
--- a/Code/Editor/Controls/FolderTreeCtrl.cpp
+++ b/Code/Editor/Controls/FolderTreeCtrl.cpp
@@ -279,7 +279,7 @@ void CFolderTreeCtrl::LoadTreeRec(const QString& currentFolder)
void CFolderTreeCtrl::AddItem(const QString& path)
{
AZ::IO::FixedMaxPath folder{ AZ::IO::PathView(path.toUtf8().constData()) };
- AZ::IO::FixedMaxPath fileNameWithoutExtension = folder.Extension();
+ AZ::IO::FixedMaxPath fileNameWithoutExtension = folder.Stem();
folder = folder.ParentPath();
auto regex = QRegExp(m_fileNameSpec, Qt::CaseInsensitive, QRegExp::Wildcard);
diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp
index 75bd0ad270..4944c3bff5 100644
--- a/Code/Editor/CryEditDoc.cpp
+++ b/Code/Editor/CryEditDoc.cpp
@@ -1273,7 +1273,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename)
if (savedEntities)
{
AZ_PROFILE_SCOPE(AzToolsFramework, "CCryEditDoc::SaveLevel Updated PakFile levelEntities.editor_xml");
- pakFile.UpdateFile("LevelEntities.editor_xml", entitySaveBuffer.begin(), static_cast(entitySaveBuffer.size()));
+ pakFile.UpdateFile("levelentities.editor_xml", entitySaveBuffer.begin(), static_cast(entitySaveBuffer.size()));
// Save XML archive to pak file.
bool bSaved = xmlAr.SaveToPak(Path::GetPath(tempSaveFile), pakFile);
@@ -1501,7 +1501,7 @@ bool CCryEditDoc::LoadEntitiesFromLevel(const QString& levelPakFile)
bool pakOpened = pakSystem->OpenPack(levelPakFile.toUtf8().data());
if (pakOpened)
{
- const QString entityFilename = Path::GetPath(levelPakFile) + "LevelEntities.editor_xml";
+ const QString entityFilename = Path::GetPath(levelPakFile) + "levelentities.editor_xml";
CCryFile entitiesFile;
if (entitiesFile.Open(entityFilename.toUtf8().data(), "rt"))
diff --git a/Code/Editor/Util/XmlArchive.cpp b/Code/Editor/Util/XmlArchive.cpp
index 18c3fc8e63..3a965fb239 100644
--- a/Code/Editor/Util/XmlArchive.cpp
+++ b/Code/Editor/Util/XmlArchive.cpp
@@ -119,7 +119,7 @@ bool CXmlArchive::SaveToPak([[maybe_unused]] const QString& levelPath, CPakFile&
_smart_ptr pXmlStrData = root->getXMLData(5000000);
// Save xml file.
- QString xmlFilename = "Level.editor_xml";
+ QString xmlFilename = "level.editor_xml";
pakFile.UpdateFile(xmlFilename.toUtf8().data(), (void*)pXmlStrData->GetString(), static_cast(pXmlStrData->GetStringLength()));
if (pakFile.GetArchive())
@@ -134,7 +134,7 @@ bool CXmlArchive::SaveToPak([[maybe_unused]] const QString& levelPath, CPakFile&
//////////////////////////////////////////////////////////////////////////
bool CXmlArchive::LoadFromPak(const QString& levelPath, CPakFile& pakFile)
{
- QString xmlFilename = QDir(levelPath).absoluteFilePath("Level.editor_xml");
+ QString xmlFilename = QDir(levelPath).absoluteFilePath("level.editor_xml");
root = XmlHelpers::LoadXmlFromFile(xmlFilename.toUtf8().data());
if (!root)
{
diff --git a/Code/Framework/AzCore/AzCore/EBus/EBus.h b/Code/Framework/AzCore/AzCore/EBus/EBus.h
index a3dc10b103..67cffb4e41 100644
--- a/Code/Framework/AzCore/AzCore/EBus/EBus.h
+++ b/Code/Framework/AzCore/AzCore/EBus/EBus.h
@@ -77,9 +77,11 @@ namespace AZ
public:
/**
* Allocator used by the EBus.
- * The default setting is AZStd::allocator, which uses AZ::SystemAllocator.
+ * The default setting is Internal EBusEnvironmentAllocator
+ * EBus code stores their Context instances in static memory
+ * Therfore the configured allocator must last as long as the EBus in a module
*/
- using AllocatorType = AZStd::allocator;
+ using AllocatorType = AZ::Internal::EBusEnvironmentAllocator;
/**
* Defines how many handlers can connect to an address on the EBus
diff --git a/Code/Framework/AzCore/AzCore/Memory/AllocatorManager.h b/Code/Framework/AzCore/AzCore/Memory/AllocatorManager.h
index be0ab4a0a0..14dec68ad1 100644
--- a/Code/Framework/AzCore/AzCore/Memory/AllocatorManager.h
+++ b/Code/Framework/AzCore/AzCore/Memory/AllocatorManager.h
@@ -34,7 +34,9 @@ namespace AZ
friend IAllocator;
friend class AllocatorBase;
friend class Debug::AllocationRecords;
- friend class AZ::Internal::EnvironmentVariableHolder;
+ template friend constexpr auto AZStd::construct_at(T*, Args&&... args)
+ ->AZStd::enable_if_t()) T(AZStd::forward(args)...))>>, T*>;
+ template constexpr friend void AZStd::destroy_at(T*);
public:
typedef AZStd::function OutOfMemoryCBType;
diff --git a/Code/Framework/AzCore/AzCore/Module/Environment.h b/Code/Framework/AzCore/AzCore/Module/Environment.h
index e87ff81446..a2dcfbd8fa 100644
--- a/Code/Framework/AzCore/AzCore/Module/Environment.h
+++ b/Code/Framework/AzCore/AzCore/Module/Environment.h
@@ -251,16 +251,15 @@ namespace AZ
class EnvironmentVariableHolder
: public EnvironmentVariableHolderBase
{
- void ConstructImpl(const AZStd::true_type& /* AZStd::has_trivial_constructor */)
- {
- memset(&m_value, 0, sizeof(T));
- }
-
template
- void ConstructImpl(const AZStd::false_type& /* AZStd::has_trivial_constructor */, Args&&... args)
+ void ConstructImpl(Args&&... args)
{
- // Construction of non-trivial types is left up to the type's constructor.
- new(&m_value) T(AZStd::forward(args)...);
+ // Use std::launder to ensure that the compiler treats the T* reinterpret_cast as a new object
+ #if __cpp_lib_launder
+ AZStd::construct_at(std::launder(reinterpret_cast(&m_value)), AZStd::forward(args)...);
+ #else
+ AZStd::construct_at(reinterpret_cast(&m_value), AZStd::forward(args)...);
+ #endif
}
static void DestructDispatchNoLock(EnvironmentVariableHolderBase *base, DestroyTarget selfDestruct)
{
@@ -274,10 +273,12 @@ namespace AZ
AZ_Assert(self->m_isConstructed, "Variable is not constructed. Please check your logic and guard if needed!");
self->m_isConstructed = false;
self->m_moduleOwner = nullptr;
- if constexpr(!AZStd::is_trivially_destructible_v)
- {
- reinterpret_cast(&self->m_value)->~T();
- }
+ // Use std::launder to ensure that the compiler treats the T* reinterpret_cast as a new object
+ #if __cpp_lib_launder
+ AZStd::destroy_at(std::launder(reinterpret_cast(&self->m_value)));
+ #else
+ AZStd::destroy_at(reinterpret_cast(&self->m_value));
+ #endif
}
public:
EnvironmentVariableHolder(u32 guid, bool isOwnershipTransfer, Environment::AllocatorInterface* allocator)
@@ -303,24 +304,13 @@ namespace AZ
UnregisterAndDestroy(DestructDispatchNoLock, moduleRelease);
}
- void Construct()
- {
- AZStd::lock_guard lock(m_mutex);
- if (!m_isConstructed)
- {
- ConstructImpl(AZStd::is_trivially_constructible{});
- m_isConstructed = true;
- m_moduleOwner = Environment::GetModuleId();
- }
- }
-
template
void Construct(Args&&... args)
{
AZStd::lock_guard lock(m_mutex);
if (!m_isConstructed)
{
- ConstructImpl(typename AZStd::false_type(), AZStd::forward(args)...);
+ ConstructImpl(AZStd::forward(args)...);
m_isConstructed = true;
m_moduleOwner = Environment::GetModuleId();
}
@@ -333,7 +323,7 @@ namespace AZ
}
// variable storage
- typename AZStd::aligned_storage::value>::type m_value;
+ AZStd::aligned_storage_for_t m_value;
static int s_moduleUseCount;
};
@@ -468,6 +458,11 @@ namespace AZ
Get() = value;
}
+ void Set(T&& value)
+ {
+ Get() = AZStd::move(value);
+ }
+
explicit operator bool() const
{
return IsValid();
diff --git a/Code/Framework/AzCore/AzCore/Name/Internal/NameData.cpp b/Code/Framework/AzCore/AzCore/Name/Internal/NameData.cpp
index 0086e68c6d..574b0bcc7e 100644
--- a/Code/Framework/AzCore/AzCore/Name/Internal/NameData.cpp
+++ b/Code/Framework/AzCore/AzCore/Name/Internal/NameData.cpp
@@ -42,7 +42,10 @@ namespace AZ
AZ_Assert(m_useCount > 0, "m_useCount is already 0!");
if (m_useCount.fetch_sub(1) == 1)
{
- AZ::NameDictionary::Instance().TryReleaseName(hash);
+ if (AZ::NameDictionary::IsReady())
+ {
+ AZ::NameDictionary::Instance().TryReleaseName(hash);
+ }
}
}
}
diff --git a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp
index 8e8011add9..3047a2894e 100644
--- a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp
+++ b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp
@@ -21,23 +21,18 @@ namespace AZ
namespace NameDictionaryInternal
{
- static AZ::EnvironmentVariable s_instance = nullptr;
+ static AZ::EnvironmentVariable s_instance = nullptr;
}
void NameDictionary::Create()
{
using namespace NameDictionaryInternal;
- AZ_Assert(!s_instance || !s_instance.Get(), "NameDictionary already created!");
+ AZ_Assert(!s_instance, "NameDictionary already created!");
if (!s_instance)
{
- s_instance = AZ::Environment::CreateVariable(NameDictionaryInstanceName);
- }
-
- if (!s_instance.Get())
- {
- s_instance.Set(aznew NameDictionary());
+ s_instance = AZ::Environment::CreateVariable(NameDictionaryInstanceName);
}
}
@@ -46,8 +41,7 @@ namespace AZ
using namespace NameDictionaryInternal;
AZ_Assert(s_instance, "NameDictionary not created!");
- delete (*s_instance);
- *s_instance = nullptr;
+ s_instance.Reset();
}
bool NameDictionary::IsReady()
@@ -56,10 +50,10 @@ namespace AZ
if (!s_instance)
{
- s_instance = Environment::FindVariable(NameDictionaryInstanceName);
+ s_instance = Environment::FindVariable(NameDictionaryInstanceName);
}
- return s_instance && *s_instance;
+ return s_instance.IsConstructed();
}
NameDictionary& NameDictionary::Instance()
@@ -68,12 +62,12 @@ namespace AZ
if (!s_instance)
{
- s_instance = Environment::FindVariable(NameDictionaryInstanceName);
+ s_instance = Environment::FindVariable(NameDictionaryInstanceName);
}
- AZ_Assert(s_instance && *s_instance, "NameDictionary has not been initialized yet.");
+ AZ_Assert(s_instance.IsConstructed(), "NameDictionary has not been initialized yet.");
- return *(*s_instance);
+ return *s_instance;
}
NameDictionary::NameDictionary()
diff --git a/Code/Framework/AzCore/AzCore/Name/NameDictionary.h b/Code/Framework/AzCore/AzCore/Name/NameDictionary.h
index fa13dbd682..8f9af4be3a 100644
--- a/Code/Framework/AzCore/AzCore/Name/NameDictionary.h
+++ b/Code/Framework/AzCore/AzCore/Name/NameDictionary.h
@@ -16,7 +16,7 @@
#include
#include
-namespace MaterialEditor
+namespace MaterialEditor
{
class MaterialEditorCoreComponent;
}
@@ -34,14 +34,14 @@ namespace AZ
{
class NameData;
};
-
+
//! Maintains a list of unique strings for Name objects.
//! The main benefit of the Name system is very fast string equality comparison, because every
- //! unique name has a unique ID. The NameDictionary's purpose is to guarantee name IDs do not
+ //! unique name has a unique ID. The NameDictionary's purpose is to guarantee name IDs do not
//! collide. It also saves memory by removing duplicate strings.
//!
- //! Benchmarks have shown that creating a new Name object can be quite slow when the name doesn't
- //! already exist in the NameDictionary, but is comparable to creating an AZStd::string for names
+ //! Benchmarks have shown that creating a new Name object can be quite slow when the name doesn't
+ //! already exist in the NameDictionary, but is comparable to creating an AZStd::string for names
//! that already exist.
class NameDictionary final
{
@@ -51,7 +51,10 @@ namespace AZ
friend Name;
friend Internal::NameData;
friend UnitTest::NameDictionaryTester;
-
+ template friend constexpr auto AZStd::construct_at(T*, Args&&... args)
+ -> AZStd::enable_if_t()) T(AZStd::forward(args)...))>>, T*>;
+ template constexpr friend void AZStd::destroy_at(T*);
+
public:
static void Create();
@@ -62,7 +65,7 @@ namespace AZ
//! Makes a Name from the provided raw string. If an entry already exists in the dictionary, it is shared.
//! Otherwise, it is added to the internal dictionary.
- //!
+ //!
//! @param name The name to resolve against the dictionary.
//! @return A Name instance holding a dictionary entry associated with the provided raw string.
Name MakeName(AZStd::string_view name);
@@ -84,13 +87,13 @@ namespace AZ
// Attempts to release the name from the dictionary, but checks to make sure
// a reference wasn't taken by another thread.
void TryReleaseName(Name::Hash hash);
-
+
//////////////////////////////////////////////////////////////////////////
// Calculates a hash for the provided name string.
// Does not attempt to resolve hash collisions; that is handled elsewhere.
Name::Hash CalcHash(AZStd::string_view name);
-
+
AZStd::unordered_map m_dictionary;
mutable AZStd::shared_mutex m_sharedMutex;
};
diff --git a/Code/Framework/AzCore/AzCore/std/allocator_stateless.cpp b/Code/Framework/AzCore/AzCore/std/allocator_stateless.cpp
new file mode 100644
index 0000000000..5806cc485c
--- /dev/null
+++ b/Code/Framework/AzCore/AzCore/std/allocator_stateless.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+
+namespace AZStd
+{
+ stateless_allocator::stateless_allocator(const char* name)
+ : m_name(name) {}
+
+ const char* stateless_allocator::get_name() const
+ {
+ return m_name;
+ }
+
+ void stateless_allocator::set_name(const char* name)
+ {
+ m_name = name;
+ }
+
+ auto stateless_allocator::allocate(size_type byteSize) -> pointer_type
+ {
+ return allocate(byteSize, AZ_DEFAULT_ALIGNMENT, 0);
+ }
+
+ auto stateless_allocator::allocate(size_type byteSize, size_type alignment, int) -> pointer_type
+ {
+ pointer_type address = AZ_OS_MALLOC(byteSize, alignment);
+
+ if (address == nullptr)
+ {
+ AZ_Error("Memory", false, "stateless_allocator ran out of system memory!\n");
+ }
+
+ return address;
+ }
+
+ void stateless_allocator::deallocate(pointer_type ptr, size_type)
+ {
+ AZ_OS_FREE(ptr);
+ }
+
+ void stateless_allocator::deallocate(pointer_type ptr, size_type, size_type)
+ {
+ AZ_OS_FREE(ptr);
+ }
+
+ auto stateless_allocator::max_size() const -> size_type
+ {
+ return AZ_CORE_MAX_ALLOCATOR_SIZE;
+ }
+
+ stateless_allocator stateless_allocator::select_on_container_copy_construction() const
+ {
+ return *this;
+ }
+
+ auto stateless_allocator::resize(pointer_type, size_type) -> size_type
+ {
+ return 0;
+ }
+
+ bool stateless_allocator::is_lock_free()
+ {
+ return false;
+ }
+
+ bool stateless_allocator::is_stale_read_allowed()
+ {
+ return false;
+ }
+
+ bool stateless_allocator::is_delayed_recycling()
+ {
+ return false;
+ }
+
+ // comparison operators
+ bool operator==(const stateless_allocator&, const stateless_allocator&)
+ {
+ return true;
+ }
+
+ bool operator!=(const stateless_allocator&, const stateless_allocator&)
+ {
+ return false;
+ }
+}
diff --git a/Code/Framework/AzCore/AzCore/std/allocator_stateless.h b/Code/Framework/AzCore/AzCore/std/allocator_stateless.h
new file mode 100644
index 0000000000..b73c680c32
--- /dev/null
+++ b/Code/Framework/AzCore/AzCore/std/allocator_stateless.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+#include
+
+namespace AZStd
+{
+ class stateless_allocator
+ {
+ public:
+
+ AZ_TYPE_INFO(stateless_allocator, "{E4976C53-0B20-4F39-8D41-0A76F59A7D68}");
+
+ using value_type = uint8_t;
+ using pointer_type = void*;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+ using allow_memory_leaks = AZStd::true_type;
+
+ stateless_allocator(const char* name = "AZStd::stateless_allocator");
+ stateless_allocator(const stateless_allocator& rhs) = default;
+
+ stateless_allocator& operator=(const stateless_allocator& rhs) = default;
+
+ const char* get_name() const;
+ void set_name(const char* name);
+
+ pointer_type allocate(size_type byteSize);
+ pointer_type allocate(size_type byteSize, size_type alignment, int flags = 0);
+ void deallocate(pointer_type ptr, size_type alignment);
+ void deallocate(pointer_type ptr, size_type byteSize, size_type alignment);
+
+ // max_size actually returns the true maximum size of a single allocation
+ size_type max_size() const;
+
+ // Returns a copy of the allocator
+ stateless_allocator select_on_container_copy_construction() const;
+
+ //! extensions
+ size_type resize(pointer_type ptr, size_type newSize);
+
+ bool is_lock_free();
+ bool is_stale_read_allowed();
+ bool is_delayed_recycling();
+
+ private:
+ const char* m_name;
+ };
+
+ bool operator==(const stateless_allocator& left, const stateless_allocator& right);
+ bool operator!=(const stateless_allocator& left, const stateless_allocator& right);
+}
diff --git a/Code/Framework/AzCore/AzCore/std/azstd_files.cmake b/Code/Framework/AzCore/AzCore/std/azstd_files.cmake
index 08e72c5649..2746489f8c 100644
--- a/Code/Framework/AzCore/AzCore/std/azstd_files.cmake
+++ b/Code/Framework/AzCore/AzCore/std/azstd_files.cmake
@@ -12,6 +12,8 @@ set(FILES
allocator.h
allocator_ref.h
allocator_stack.h
+ allocator_stateless.cpp
+ allocator_stateless.h
allocator_static.h
allocator_traits.h
any.h
diff --git a/Code/Framework/AzCore/AzCore/std/createdestroy.h b/Code/Framework/AzCore/AzCore/std/createdestroy.h
index 0fa6e4ed40..355374a13a 100644
--- a/Code/Framework/AzCore/AzCore/std/createdestroy.h
+++ b/Code/Framework/AzCore/AzCore/std/createdestroy.h
@@ -20,7 +20,7 @@
namespace AZStd
{
- // alias std::pointer_traits into the AZStd::namespace
+ // alias std::pointer_traits into the AZStd::namespace
using std::pointer_traits;
//! Bring the names of uninitialized_default_construct and
@@ -229,7 +229,7 @@ namespace AZStd
//! `new (declval()) T(declval()...)` is well-formed
template
constexpr auto construct_at(T* ptr, Args&&... args)
- -> enable_if_t()) T(AZStd::forward(args)...))>>, T*>
+ -> enable_if_t()) T(AZStd::forward(args)...))>>, T*>
{
return ::new (ptr) T(AZStd::forward(args)...);
}
@@ -487,7 +487,7 @@ namespace AZStd
{
//! Implements the C++17 uninitialized_move function
//! The functions accepts two input iterators and an output iterator
- //! It performs an AZStd::move on each in in the range of the input iterator
+ //! It performs an AZStd::move on each in in the range of the input iterator
//! and stores the result in location pointed by the output iterator
template
ForwardIt uninitialized_move(InputIt first, InputIt last, ForwardIt result)
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h
index 45da3a9d8f..2d7d9dc511 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h
@@ -11,6 +11,8 @@
#include
#include
+#include
+
namespace AzToolsFramework
{
//! Outcome object that returns an error message in case of failure to allow caller to handle internal errors.
@@ -43,7 +45,7 @@ namespace AzToolsFramework
//! @param entityId The entityId whose open state will be set.
//! @param open True if the container should be opened, false if it should be closed.
//! @return An error message if the operation was invalid, success otherwise.
- virtual ContainerEntityOperationResult SetContainerOpenState(AZ::EntityId entityId, bool open) = 0;
+ virtual ContainerEntityOperationResult SetContainerOpen(AZ::EntityId entityId, bool open) = 0;
//! If the entity id provided is registered as a container, it returns whether it's open.
//! @note the default value for non-containers is true, so this function can be called without
@@ -56,6 +58,16 @@ namespace AzToolsFramework
//! @return The highest closed entity container id if any, or entityId otherwise.
virtual AZ::EntityId FindHighestSelectableEntity(AZ::EntityId entityId) const = 0;
+ //! Clears all open state information for Container Entities for the EntityContextId provided.
+ //! Used when context is switched, for example in the case of a new root prefab being loaded
+ //! in place of an old one.
+ //! @note Clear is meant to be called when no container is registered for the context provided.
+ //! @return An error message if any container was registered for the context, success otherwise.
+ virtual ContainerEntityOperationResult Clear(AzFramework::EntityContextId entityContextId) = 0;
+
+ //! Returns true if one of the ancestors of entityId is a closed container entity.
+ virtual bool IsUnderClosedContainerEntity(AZ::EntityId entityId) const = 0;
+
};
} // namespace AzToolsFramework
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp
index 0ea2eeb5f6..61b257a189 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp
@@ -10,16 +10,19 @@
#include
#include
+#include
namespace AzToolsFramework
{
void ContainerEntitySystemComponent::Activate()
{
AZ::Interface::Register(this);
+ EditorEntityContextNotificationBus::Handler::BusConnect();
}
void ContainerEntitySystemComponent::Deactivate()
{
+ EditorEntityContextNotificationBus::Handler::BusDisconnect();
AZ::Interface::Unregister(this);
}
@@ -63,7 +66,7 @@ namespace AzToolsFramework
return m_containers.contains(entityId);
}
- ContainerEntityOperationResult ContainerEntitySystemComponent::SetContainerOpenState(AZ::EntityId entityId, bool open)
+ ContainerEntityOperationResult ContainerEntitySystemComponent::SetContainerOpen(AZ::EntityId entityId, bool open)
{
if (!IsContainer(entityId))
{
@@ -87,7 +90,7 @@ namespace AzToolsFramework
bool ContainerEntitySystemComponent::IsContainerOpen(AZ::EntityId entityId) const
{
- // If the entity is not a container, it should behave as open.
+ // Non-container entities behave the same as open containers. This saves the caller an additional check.
if(!m_containers.contains(entityId))
{
return true;
@@ -99,8 +102,17 @@ namespace AzToolsFramework
AZ::EntityId ContainerEntitySystemComponent::FindHighestSelectableEntity(AZ::EntityId entityId) const
{
+ if (!entityId.IsValid())
+ {
+ return entityId;
+ }
+
+ // Return the highest closed container, or the entity if none is found.
AZ::EntityId highestSelectableEntityId = entityId;
+ // Skip the queried entity, as we only want to check its ancestors.
+ AZ::TransformBus::EventResult(entityId, entityId, &AZ::TransformBus::Events::GetParentId);
+
// Go up the hierarchy until you hit the root
while (entityId.IsValid())
{
@@ -117,4 +129,72 @@ namespace AzToolsFramework
return highestSelectableEntityId;
}
+ void ContainerEntitySystemComponent::OnEntityStreamLoadSuccess()
+ {
+ // We don't yet support multiple entity contexts, so just use the default.
+ auto editorEntityContextId = AzFramework::EntityContextId::CreateNull();
+ EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
+
+ Clear(editorEntityContextId);
+ }
+
+ ContainerEntityOperationResult ContainerEntitySystemComponent::Clear(AzFramework::EntityContextId entityContextId)
+ {
+ // We don't yet support multiple entity contexts, so only clear the default.
+ auto editorEntityContextId = AzFramework::EntityContextId::CreateNull();
+ EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
+
+ if (entityContextId != editorEntityContextId)
+ {
+ return AZ::Failure(AZStd::string(
+ "Error in ContainerEntitySystemComponent::Clear - cannot clear non-default Entity Context!"));
+ }
+
+ if (!m_containers.empty())
+ {
+ return AZ::Failure(AZStd::string(
+ "Error in ContainerEntitySystemComponent::Clear - cannot clear container states if entities are still registered!"));
+ }
+
+ m_openContainers.clear();
+
+ return AZ::Success();
+ }
+
+ bool ContainerEntitySystemComponent::IsUnderClosedContainerEntity(AZ::EntityId entityId) const
+ {
+ if (!entityId.IsValid())
+ {
+ return false;
+ }
+
+ // Skip the queried entity, as we only want to check its ancestors.
+ AZ::TransformBus::EventResult(entityId, entityId, &AZ::TransformBus::Events::GetParentId);
+
+ // Go up the hierarchy until you hit the root.
+ while (entityId.IsValid())
+ {
+ if (!IsContainerOpen(entityId))
+ {
+ // One of the ancestors is a container and it's closed.
+ return true;
+ }
+
+ AZ::EntityId parentId;
+ AZ::TransformBus::EventResult(parentId, entityId, &AZ::TransformBus::Events::GetParentId);
+
+ if (parentId == entityId)
+ {
+ // In some circumstances, querying a root level entity with GetParentId will return
+ // the entity itself instead of an invalid entityId.
+ break;
+ }
+
+ entityId = parentId;
+ }
+
+ // All ancestors are either regular entities or open containers.
+ return false;
+ }
+
} // namespace AzToolsFramework
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h
index 18c0fb70c6..7a11e05096 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h
@@ -12,6 +12,7 @@
#include
#include
+#include
namespace AzToolsFramework
{
@@ -23,6 +24,7 @@ namespace AzToolsFramework
class ContainerEntitySystemComponent final
: public AZ::Component
, private ContainerEntityInterface
+ , private EditorEntityContextNotificationBus::Handler
{
public:
AZ_COMPONENT(ContainerEntitySystemComponent, "{74349759-B36B-44A6-B89F-F45D7111DD11}");
@@ -42,9 +44,14 @@ namespace AzToolsFramework
ContainerEntityOperationResult RegisterEntityAsContainer(AZ::EntityId entityId) override;
ContainerEntityOperationResult UnregisterEntityAsContainer(AZ::EntityId entityId) override;
bool IsContainer(AZ::EntityId entityId) const override;
- ContainerEntityOperationResult SetContainerOpenState(AZ::EntityId entityId, bool open) override;
+ ContainerEntityOperationResult SetContainerOpen(AZ::EntityId entityId, bool open) override;
bool IsContainerOpen(AZ::EntityId entityId) const override;
AZ::EntityId FindHighestSelectableEntity(AZ::EntityId entityId) const override;
+ ContainerEntityOperationResult Clear(AzFramework::EntityContextId entityContextId) override;
+ bool IsUnderClosedContainerEntity(AZ::EntityId entityId) const override;
+
+ // EditorEntityContextNotificationBus overrides ...
+ void OnEntityStreamLoadSuccess() override;
private:
AZStd::unordered_set m_containers; //!< All entities in this set are containers.
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp
index 7789070209..8d40162f52 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp
@@ -16,9 +16,11 @@
#include
#include
#include
+#include
#include
#include
#include
+#include
#include
#include
#include
@@ -588,15 +590,40 @@ namespace AzToolsFramework
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
+ // Detect if the Entity is Visible
bool visible = false;
EditorEntityInfoRequestBus::EventResult(
visible, entityId, &EditorEntityInfoRequestBus::Events::IsVisible);
- bool locked = false;
- EditorEntityInfoRequestBus::EventResult(
- locked, entityId, &EditorEntityInfoRequestBus::Events::IsLocked);
+ if (!visible)
+ {
+ return false;
+ }
- return visible && !locked;
+ // Detect if the Entity is Locked
+ bool locked = false;
+ EditorEntityInfoRequestBus::EventResult(locked, entityId, &EditorEntityInfoRequestBus::Events::IsLocked);
+
+ if (locked)
+ {
+ return false;
+ }
+
+ // Detect if the Entity is part of the Editor Focus
+ if (auto focusModeInterface = AZ::Interface::Get();
+ !focusModeInterface->IsInFocusSubTree(entityId))
+ {
+ return false;
+ }
+
+ // Detect if the Entity is a descendant of a closed container
+ if (auto containerEntityInterface = AZ::Interface::Get();
+ containerEntityInterface->IsUnderClosedContainerEntity(entityId))
+ {
+ return false;
+ }
+
+ return true;
}
static void SetEntityLockStateRecursively(
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp
index 9ffc18af5a..a79b9eb73d 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp
@@ -8,12 +8,14 @@
#include
+#include
#include
#include
#include
#include
#include
#include
+#include
namespace AzToolsFramework::Prefab
{
@@ -28,10 +30,12 @@ namespace AzToolsFramework::Prefab
EditorEntityContextNotificationBus::Handler::BusConnect();
AZ::Interface::Register(this);
+ AZ::Interface::Register(this);
}
PrefabFocusHandler::~PrefabFocusHandler()
{
+ AZ::Interface::Unregister(this);
AZ::Interface::Unregister(this);
EditorEntityContextNotificationBus::Handler::BusDisconnect();
}
@@ -61,6 +65,44 @@ namespace AzToolsFramework::Prefab
}
PrefabFocusOperationResult PrefabFocusHandler::FocusOnOwningPrefab(AZ::EntityId entityId)
+ {
+ // Initialize Undo Batch object
+ ScopedUndoBatch undoBatch("Edit Prefab");
+
+ // Clear selection
+ {
+ const EntityIdList selectedEntities = EntityIdList{};
+ auto selectionUndo = aznew SelectionCommand(selectedEntities, "Clear Selection");
+ selectionUndo->SetParent(undoBatch.GetUndoBatch());
+ ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::SetSelectedEntities, selectedEntities);
+ }
+
+ // Edit Prefab
+ {
+ auto editUndo = aznew PrefabFocusUndo("Edit Prefab");
+ editUndo->Capture(entityId);
+ editUndo->SetParent(undoBatch.GetUndoBatch());
+ ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, editUndo);
+ }
+
+ return AZ::Success();
+ }
+
+ PrefabFocusOperationResult PrefabFocusHandler::FocusOnPathIndex([[maybe_unused]] AzFramework::EntityContextId entityContextId, int index)
+ {
+ if (index < 0 || index >= m_instanceFocusVector.size())
+ {
+ return AZ::Failure(AZStd::string("Prefab Focus Handler: Invalid index on FocusOnPathIndex."));
+ }
+
+ InstanceOptionalReference focusedInstance = m_instanceFocusVector[index];
+
+ FocusOnOwningPrefab(focusedInstance->get().GetContainerEntityId());
+
+ return AZ::Success();
+ }
+
+ PrefabFocusOperationResult PrefabFocusHandler::FocusOnPrefabInstanceOwningEntityId(AZ::EntityId entityId)
{
InstanceOptionalReference focusedInstance;
@@ -85,18 +127,6 @@ namespace AzToolsFramework::Prefab
return FocusOnPrefabInstance(focusedInstance);
}
- PrefabFocusOperationResult PrefabFocusHandler::FocusOnPathIndex([[maybe_unused]] AzFramework::EntityContextId entityContextId, int index)
- {
- if (index < 0 || index >= m_instanceFocusVector.size())
- {
- return AZ::Failure(AZStd::string("Prefab Focus Handler: Invalid index on FocusOnPathIndex."));
- }
-
- InstanceOptionalReference focusedInstance = m_instanceFocusVector[index];
-
- return FocusOnPrefabInstance(focusedInstance);
- }
-
PrefabFocusOperationResult PrefabFocusHandler::FocusOnPrefabInstance(InstanceOptionalReference focusedInstance)
{
if (!focusedInstance.has_value())
@@ -122,17 +152,10 @@ namespace AzToolsFramework::Prefab
if (focusedInstance->get().GetParentInstance() != AZStd::nullopt)
{
containerEntityId = focusedInstance->get().GetContainerEntityId();
-
- // Select the container entity
- AzToolsFramework::SelectEntity(containerEntityId);
}
else
{
containerEntityId = AZ::EntityId();
-
- // Clear the selection
- AzToolsFramework::SelectEntities({});
-
}
// Focus on the descendants of the container entity
@@ -161,6 +184,17 @@ namespace AzToolsFramework::Prefab
return m_focusedInstance;
}
+ AZ::EntityId PrefabFocusHandler::GetFocusedPrefabContainerEntityId([[maybe_unused]] AzFramework::EntityContextId entityContextId) const
+ {
+ if (!m_focusedInstance.has_value())
+ {
+ // PrefabFocusHandler has not been initialized yet.
+ return AZ::EntityId();
+ }
+
+ return m_focusedInstance->get().GetContainerEntityId();
+ }
+
bool PrefabFocusHandler::IsOwningPrefabBeingFocused(AZ::EntityId entityId) const
{
if (!m_focusedInstance.has_value())
@@ -196,8 +230,11 @@ namespace AzToolsFramework::Prefab
Initialize();
}
+ // Clear the old focus vector
+ m_instanceFocusVector.clear();
+
// Focus on the root prefab (AZ::EntityId() will default to it)
- FocusOnOwningPrefab(AZ::EntityId());
+ FocusOnPrefabInstanceOwningEntityId(AZ::EntityId());
}
void PrefabFocusHandler::RefreshInstanceFocusList()
@@ -230,7 +267,7 @@ namespace AzToolsFramework::Prefab
{
if (instance.has_value())
{
- m_containerEntityInterface->SetContainerOpenState(instance->get().GetContainerEntityId(), true);
+ m_containerEntityInterface->SetContainerOpen(instance->get().GetContainerEntityId(), true);
}
}
}
@@ -241,7 +278,7 @@ namespace AzToolsFramework::Prefab
{
if (instance.has_value())
{
- m_containerEntityInterface->SetContainerOpenState(instance->get().GetContainerEntityId(), false);
+ m_containerEntityInterface->SetContainerOpen(instance->get().GetContainerEntityId(), false);
}
}
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h
index 2f631f772d..80b7a6859c 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h
@@ -13,6 +13,7 @@
#include
#include
#include
+#include
#include
namespace AzToolsFramework
@@ -28,6 +29,7 @@ namespace AzToolsFramework::Prefab
//! Handles Prefab Focus mode, determining which prefab file entity changes will target.
class PrefabFocusHandler final
: private PrefabFocusInterface
+ , private PrefabFocusPublicInterface
, private EditorEntityContextNotificationBus::Handler
{
public:
@@ -39,10 +41,14 @@ namespace AzToolsFramework::Prefab
void Initialize();
// PrefabFocusInterface overrides ...
- PrefabFocusOperationResult FocusOnOwningPrefab(AZ::EntityId entityId) override;
- PrefabFocusOperationResult FocusOnPathIndex(AzFramework::EntityContextId entityContextId, int index) override;
+ PrefabFocusOperationResult FocusOnPrefabInstanceOwningEntityId(AZ::EntityId entityId) override;
TemplateId GetFocusedPrefabTemplateId(AzFramework::EntityContextId entityContextId) const override;
InstanceOptionalReference GetFocusedPrefabInstance(AzFramework::EntityContextId entityContextId) const override;
+
+ // PrefabFocusPublicInterface overrides ...
+ PrefabFocusOperationResult FocusOnOwningPrefab(AZ::EntityId entityId) override;
+ PrefabFocusOperationResult FocusOnPathIndex(AzFramework::EntityContextId entityContextId, int index) override;
+ AZ::EntityId GetFocusedPrefabContainerEntityId(AzFramework::EntityContextId entityContextId) const override;
bool IsOwningPrefabBeingFocused(AZ::EntityId entityId) const override;
const AZ::IO::Path& GetPrefabFocusPath(AzFramework::EntityContextId entityContextId) const override;
const int GetPrefabFocusPathLength(AzFramework::EntityContextId entityContextId) const override;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h
index 1c0f4f85e9..25c83b89bc 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h
@@ -20,7 +20,7 @@ namespace AzToolsFramework::Prefab
{
using PrefabFocusOperationResult = AZ::Outcome;
- //! Interface to handle operations related to the Prefab Focus system.
+ //! Interface to handle internal operations related to the Prefab Focus system.
class PrefabFocusInterface
{
public:
@@ -28,29 +28,13 @@ namespace AzToolsFramework::Prefab
//! Set the focused prefab instance to the owning instance of the entityId provided.
//! @param entityId The entityId of the entity whose owning instance we want the prefab system to focus on.
- virtual PrefabFocusOperationResult FocusOnOwningPrefab(AZ::EntityId entityId) = 0;
-
- //! Set the focused prefab instance to the instance at position index of the current path.
- //! @param index The index of the instance in the current path that we want the prefab system to focus on.
- virtual PrefabFocusOperationResult FocusOnPathIndex(AzFramework::EntityContextId entityContextId, int index) = 0;
+ virtual PrefabFocusOperationResult FocusOnPrefabInstanceOwningEntityId(AZ::EntityId entityId) = 0;
//! Returns the template id of the instance the prefab system is focusing on.
virtual TemplateId GetFocusedPrefabTemplateId(AzFramework::EntityContextId entityContextId) const = 0;
//! Returns a reference to the instance the prefab system is focusing on.
virtual InstanceOptionalReference GetFocusedPrefabInstance(AzFramework::EntityContextId entityContextId) const = 0;
-
- //! Returns whether the entity belongs to the instance that is being focused on, or one of its descendants.
- //! @param entityId The entityId of the queried entity.
- //! @return true if the entity belongs to the focused instance or one of its descendants, false otherwise.
- virtual bool IsOwningPrefabBeingFocused(AZ::EntityId entityId) const = 0;
-
- //! Returns the path from the root instance to the currently focused instance.
- //! @return A path composed from the names of the container entities for the instance path.
- virtual const AZ::IO::Path& GetPrefabFocusPath(AzFramework::EntityContextId entityContextId) const = 0;
-
- //! Returns the size of the path to the currently focused instance.
- virtual const int GetPrefabFocusPathLength(AzFramework::EntityContextId entityContextId) const = 0;
};
} // namespace AzToolsFramework::Prefab
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h
new file mode 100644
index 0000000000..86e476b56f
--- /dev/null
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+
+#include
+
+#include
+#include
+
+namespace AzToolsFramework::Prefab
+{
+ using PrefabFocusOperationResult = AZ::Outcome;
+
+ //! Public Interface for external systems to utilize the Prefab Focus system.
+ class PrefabFocusPublicInterface
+ {
+ public:
+ AZ_RTTI(PrefabFocusPublicInterface, "{53EE1D18-A41F-4DB1-9B73-9448F425722E}");
+
+ //! Set the focused prefab instance to the owning instance of the entityId provided. Supports undo/redo.
+ //! @param entityId The entityId of the entity whose owning instance we want the prefab system to focus on.
+ virtual PrefabFocusOperationResult FocusOnOwningPrefab(AZ::EntityId entityId) = 0;
+
+ //! Set the focused prefab instance to the instance at position index of the current path. Supports undo/redo.
+ //! @param index The index of the instance in the current path that we want the prefab system to focus on.
+ virtual PrefabFocusOperationResult FocusOnPathIndex(AzFramework::EntityContextId entityContextId, int index) = 0;
+
+ //! Returns the entity id of the container entity for the instance the prefab system is focusing on.
+ virtual AZ::EntityId GetFocusedPrefabContainerEntityId(AzFramework::EntityContextId entityContextId) const = 0;
+
+ //! Returns whether the entity belongs to the instance that is being focused on, or one of its descendants.
+ //! @param entityId The entityId of the queried entity.
+ //! @return true if the entity belongs to the focused instance or one of its descendants, false otherwise.
+ virtual bool IsOwningPrefabBeingFocused(AZ::EntityId entityId) const = 0;
+
+ //! Returns the path from the root instance to the currently focused instance.
+ //! @return A path composed from the names of the container entities for the instance path.
+ virtual const AZ::IO::Path& GetPrefabFocusPath(AzFramework::EntityContextId entityContextId) const = 0;
+
+ //! Returns the size of the path to the currently focused instance.
+ virtual const int GetPrefabFocusPathLength(AzFramework::EntityContextId entityContextId) const = 0;
+ };
+
+} // namespace AzToolsFramework::Prefab
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.cpp
new file mode 100644
index 0000000000..e5f664ea38
--- /dev/null
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+
+namespace AzToolsFramework::Prefab
+{
+ PrefabFocusUndo::PrefabFocusUndo(const AZStd::string& undoOperationName)
+ : UndoSystem::URSequencePoint(undoOperationName)
+ {
+ m_prefabFocusInterface = AZ::Interface::Get();
+ AZ_Assert(m_prefabFocusInterface, "PrefabFocusUndo - Failed to grab prefab focus interface");
+
+ m_prefabFocusPublicInterface = AZ::Interface::Get();
+ AZ_Assert(m_prefabFocusPublicInterface, "PrefabFocusUndo - Failed to grab prefab focus public interface");
+ }
+
+ bool PrefabFocusUndo::Changed() const
+ {
+ return true;
+ }
+
+ void PrefabFocusUndo::Capture(AZ::EntityId entityId)
+ {
+ auto entityContextId = AzFramework::EntityContextId::CreateNull();
+ EditorEntityContextRequestBus::BroadcastResult(entityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
+
+ m_beforeEntityId = m_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(entityContextId);
+ m_afterEntityId = entityId;
+ }
+
+ void PrefabFocusUndo::Undo()
+ {
+ m_prefabFocusInterface->FocusOnPrefabInstanceOwningEntityId(m_beforeEntityId);
+ }
+
+ void PrefabFocusUndo::Redo()
+ {
+ m_prefabFocusInterface->FocusOnPrefabInstanceOwningEntityId(m_afterEntityId);
+ }
+
+} // namespace AzToolsFramework::Prefab
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.h
new file mode 100644
index 0000000000..3b257b6547
--- /dev/null
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace AzToolsFramework::Prefab
+{
+ class PrefabFocusInterface;
+ class PrefabFocusPublicInterface;
+
+ //! Undo node for prefab focus change operations.
+ class PrefabFocusUndo
+ : public UndoSystem::URSequencePoint
+ {
+ public:
+ explicit PrefabFocusUndo(const AZStd::string& undoOperationName);
+
+ bool Changed() const override;
+ void Capture(AZ::EntityId entityId);
+
+ void Undo() override;
+ void Redo() override;
+
+ protected:
+ PrefabFocusInterface* m_prefabFocusInterface = nullptr;
+ PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr;
+
+ AZ::EntityId m_beforeEntityId;
+ AZ::EntityId m_afterEntityId;
+ };
+} // namespace AzToolsFramework::Prefab
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
index 038f36eac9..b5f61b33bf 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
@@ -257,9 +257,10 @@ namespace AzToolsFramework
// Select Container Entity
{
- auto selectionUndo = aznew SelectionCommand({ containerEntityId }, "Select Prefab Container Entity");
+ const EntityIdList selectedEntities = EntityIdList{ containerEntityId };
+ auto selectionUndo = aznew SelectionCommand(selectedEntities, "Select Prefab Container Entity");
selectionUndo->SetParent(undoBatch.GetUndoBatch());
- ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, selectionUndo);
+ ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::SetSelectedEntities, selectedEntities);
}
}
@@ -1097,7 +1098,7 @@ namespace AzToolsFramework
// Select the duplicated entities/instances
auto selectionUndo = aznew SelectionCommand(duplicatedEntityAndInstanceIds, "Select Duplicated Entities/Instances");
selectionUndo->SetParent(undoBatch.GetUndoBatch());
- ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, selectionUndo);
+ ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::SetSelectedEntities, duplicatedEntityAndInstanceIds);
}
return AZ::Success();
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h
index 6f074da878..acd8ba3966 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h
@@ -90,7 +90,7 @@ namespace AzToolsFramework
typedef SharedThumbnailKey BusIdType;
//! notify product thumbnail that the data is ready
- virtual void ThumbnailRendered(QPixmap& thumbnailImage) = 0;
+ virtual void ThumbnailRendered(const QPixmap& thumbnailImage) = 0;
//! notify product thumbnail that the thumbnail failed to render
virtual void ThumbnailFailedToRender() = 0;
};
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
index 459b39a290..3b48cc4967 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
@@ -324,7 +324,8 @@ namespace AzToolsFramework
// Currently, the first behavior is implemented.
void EntityOutlinerWidget::OnSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected)
{
- if (m_selectionChangeInProgress || !m_enableSelectionUpdates)
+ if (m_selectionChangeInProgress || !m_enableSelectionUpdates
+ || (selected.empty() && deselected.empty()))
{
return;
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
index d4b227c4ff..6ffa3aab69 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
@@ -24,11 +24,11 @@
#include
#include
#include
-#include
+#include
+#include
+#include
#include
#include
-#include
-#include
#include
#include
#include
@@ -39,7 +39,6 @@
#include
#include
-
#include
#include
#include
@@ -56,14 +55,13 @@
#include
#include
-
namespace AzToolsFramework
{
namespace Prefab
{
ContainerEntityInterface* PrefabIntegrationManager::s_containerEntityInterface = nullptr;
EditorEntityUiInterface* PrefabIntegrationManager::s_editorEntityUiInterface = nullptr;
- PrefabFocusInterface* PrefabIntegrationManager::s_prefabFocusInterface = nullptr;
+ PrefabFocusPublicInterface* PrefabIntegrationManager::s_prefabFocusPublicInterface = nullptr;
PrefabLoaderInterface* PrefabIntegrationManager::s_prefabLoaderInterface = nullptr;
PrefabPublicInterface* PrefabIntegrationManager::s_prefabPublicInterface = nullptr;
PrefabSystemComponentInterface* PrefabIntegrationManager::s_prefabSystemComponentInterface = nullptr;
@@ -129,14 +127,15 @@ namespace AzToolsFramework
return;
}
- s_prefabFocusInterface = AZ::Interface::Get();
- if (s_prefabFocusInterface == nullptr)
+ s_prefabFocusPublicInterface = AZ::Interface::Get();
+ if (s_prefabFocusPublicInterface == nullptr)
{
- AZ_Assert(false, "Prefab - could not get PrefabFocusInterface on PrefabIntegrationManager construction.");
+ AZ_Assert(false, "Prefab - could not get PrefabFocusPublicInterface on PrefabIntegrationManager construction.");
return;
}
EditorContextMenuBus::Handler::BusConnect();
+ EditorEventsBus::Handler::BusConnect();
PrefabInstanceContainerNotificationBus::Handler::BusConnect();
AZ::Interface::Register(this);
AssetBrowser::AssetBrowserSourceDropBus::Handler::BusConnect(s_prefabFileExtension);
@@ -147,6 +146,7 @@ namespace AzToolsFramework
AssetBrowser::AssetBrowserSourceDropBus::Handler::BusDisconnect();
AZ::Interface::Unregister(this);
PrefabInstanceContainerNotificationBus::Handler::BusDisconnect();
+ EditorEventsBus::Handler::BusDisconnect();
EditorContextMenuBus::Handler::BusDisconnect();
}
@@ -245,12 +245,8 @@ namespace AzToolsFramework
if (s_prefabPublicInterface->IsInstanceContainerEntity(selectedEntity))
{
// Edit Prefab
- if (prefabWipFeaturesEnabled)
+ if (prefabWipFeaturesEnabled && !s_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(selectedEntity))
{
- bool beingEdited = s_prefabFocusInterface->IsOwningPrefabBeingFocused(selectedEntity);
-
- if (!beingEdited)
- {
QAction* editAction = menu->addAction(QObject::tr("Edit Prefab"));
editAction->setToolTip(QObject::tr("Edit the prefab in focus mode."));
@@ -259,7 +255,6 @@ namespace AzToolsFramework
});
itemWasShown = true;
- }
}
// Save Prefab
@@ -313,6 +308,11 @@ namespace AzToolsFramework
}
}
+ void PrefabIntegrationManager::OnEscape()
+ {
+ s_prefabFocusPublicInterface->FocusOnOwningPrefab(AZ::EntityId());
+ }
+
void PrefabIntegrationManager::HandleSourceFileType(AZStd::string_view sourceFilePath, AZ::EntityId parentId, AZ::Vector3 position) const
{
auto instantiatePrefabOutcome = s_prefabPublicInterface->InstantiatePrefab(sourceFilePath, parentId, position);
@@ -483,7 +483,7 @@ namespace AzToolsFramework
void PrefabIntegrationManager::ContextMenu_EditPrefab(AZ::EntityId containerEntity)
{
- s_prefabFocusInterface->FocusOnOwningPrefab(containerEntity);
+ s_prefabFocusPublicInterface->FocusOnOwningPrefab(containerEntity);
}
void PrefabIntegrationManager::ContextMenu_SavePrefab(AZ::EntityId containerEntity)
@@ -1393,7 +1393,7 @@ namespace AzToolsFramework
AZStd::unique_ptr PrefabIntegrationManager::ConstructUnsavedPrefabsCard(TemplateId templateId)
{
- FlowLayout* unsavedPrefabsLayout = new FlowLayout(AzToolsFramework::GetActiveWindow());
+ FlowLayout* unsavedPrefabsLayout = new FlowLayout(nullptr);
AZStd::set dirtyTemplatePaths = s_prefabSystemComponentInterface->GetDirtyTemplatePaths(templateId);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h
index 696c05991c..e8c10c150a 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h
@@ -30,7 +30,7 @@ namespace AzToolsFramework
namespace Prefab
{
- class PrefabFocusInterface;
+ class PrefabFocusPublicInterface;
class PrefabLoaderInterface;
//! Structure for saving/retrieving user settings related to prefab workflows.
@@ -51,6 +51,7 @@ namespace AzToolsFramework
class PrefabIntegrationManager final
: public EditorContextMenuBus::Handler
+ , public EditorEventsBus::Handler
, public AssetBrowser::AssetBrowserSourceDropBus::Handler
, public PrefabInstanceContainerNotificationBus::Handler
, public PrefabIntegrationInterface
@@ -64,19 +65,22 @@ namespace AzToolsFramework
static void Reflect(AZ::ReflectContext* context);
- // EditorContextMenuBus...
+ // EditorContextMenuBus overrides ...
int GetMenuPosition() const override;
AZStd::string GetMenuIdentifier() const override;
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override;
- // EntityOutlinerSourceDropHandlingBus...
+ // EditorEventsBus overrides ...
+ void OnEscape();
+
+ // EntityOutlinerSourceDropHandlingBus overrides ...
void HandleSourceFileType(AZStd::string_view sourceFilePath, AZ::EntityId parentId, AZ::Vector3 position) const override;
- // PrefabInstanceContainerNotificationBus...
+ // PrefabInstanceContainerNotificationBus overrides ...
void OnPrefabComponentActivate(AZ::EntityId entityId) override;
void OnPrefabComponentDeactivate(AZ::EntityId entityId) override;
- // PrefabIntegrationInterface...
+ // PrefabIntegrationInterface overrides ...
AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId) override;
int ExecuteClosePrefabDialog(TemplateId templateId) override;
void ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) override;
@@ -140,7 +144,7 @@ namespace AzToolsFramework
static ContainerEntityInterface* s_containerEntityInterface;
static EditorEntityUiInterface* s_editorEntityUiInterface;
- static PrefabFocusInterface* s_prefabFocusInterface;
+ static PrefabFocusPublicInterface* s_prefabFocusPublicInterface;
static PrefabLoaderInterface* s_prefabLoaderInterface;
static PrefabPublicInterface* s_prefabPublicInterface;
static PrefabSystemComponentInterface* s_prefabSystemComponentInterface;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp
index 7d1f3485aa..00522b29dc 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp
@@ -10,7 +10,7 @@
#include
-#include
+#include
#include
#include
@@ -35,10 +35,10 @@ namespace AzToolsFramework
return;
}
- m_prefabFocusInterface = AZ::Interface::Get();
- if (m_prefabFocusInterface == nullptr)
+ m_prefabFocusPublicInterface = AZ::Interface::Get();
+ if (m_prefabFocusPublicInterface == nullptr)
{
- AZ_Assert(false, "PrefabUiHandler - could not get PrefabFocusInterface on PrefabUiHandler construction.");
+ AZ_Assert(false, "PrefabUiHandler - could not get PrefabFocusPublicInterface on PrefabUiHandler construction.");
return;
}
}
@@ -83,7 +83,7 @@ namespace AzToolsFramework
QIcon PrefabUiHandler::GenerateItemIcon(AZ::EntityId entityId) const
{
- if (m_prefabFocusInterface->IsOwningPrefabBeingFocused(entityId))
+ if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId))
{
return QIcon(m_prefabEditIconPath);
}
@@ -105,7 +105,7 @@ namespace AzToolsFramework
const bool hasVisibleChildren = index.data(EntityOutlinerListModel::ExpandedRole).value() && index.model()->hasChildren(index);
QColor backgroundColor = m_prefabCapsuleColor;
- if (m_prefabFocusInterface->IsOwningPrefabBeingFocused(entityId))
+ if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId))
{
backgroundColor = m_prefabCapsuleEditColor;
}
@@ -191,7 +191,7 @@ namespace AzToolsFramework
const bool isLastColumn = descendantIndex.column() == EntityOutlinerListModel::ColumnLockToggle;
QColor borderColor = m_prefabCapsuleColor;
- if (m_prefabFocusInterface->IsOwningPrefabBeingFocused(entityId))
+ if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId))
{
borderColor = m_prefabCapsuleEditColor;
}
@@ -329,7 +329,7 @@ namespace AzToolsFramework
if (prefabWipFeaturesEnabled)
{
// Focus on this prefab
- m_prefabFocusInterface->FocusOnOwningPrefab(entityId);
+ m_prefabFocusPublicInterface->FocusOnOwningPrefab(entityId);
}
}
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h
index bb7168f409..7c68d9fd95 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h
@@ -15,7 +15,7 @@ namespace AzToolsFramework
namespace Prefab
{
- class PrefabFocusInterface;
+ class PrefabFocusPublicInterface;
class PrefabPublicInterface;
};
@@ -39,7 +39,7 @@ namespace AzToolsFramework
void OnDoubleClick(AZ::EntityId entityId) const override;
private:
- Prefab::PrefabFocusInterface* m_prefabFocusInterface = nullptr;
+ Prefab::PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr;
Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr;
static bool IsLastVisibleChild(const QModelIndex& parent, const QModelIndex& child);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp
index 6b0de5dc53..21ada94184 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp
@@ -8,7 +8,7 @@
#include
-#include
+#include
namespace AzToolsFramework::Prefab
{
@@ -31,8 +31,8 @@ namespace AzToolsFramework::Prefab
void PrefabViewportFocusPathHandler::Initialize(AzQtComponents::BreadCrumbs* breadcrumbsWidget, QToolButton* backButton)
{
// Get reference to the PrefabFocusInterface handler
- m_prefabFocusInterface = AZ::Interface::Get();
- if (m_prefabFocusInterface == nullptr)
+ m_prefabFocusPublicInterface = AZ::Interface::Get();
+ if (m_prefabFocusPublicInterface == nullptr)
{
AZ_Assert(false, "Prefab - could not get PrefabFocusInterface on PrefabViewportFocusPathHandler construction.");
return;
@@ -46,7 +46,7 @@ namespace AzToolsFramework::Prefab
connect(m_breadcrumbsWidget, &AzQtComponents::BreadCrumbs::linkClicked, this,
[&](const QString&, int linkIndex)
{
- m_prefabFocusInterface->FocusOnPathIndex(m_editorEntityContextId, linkIndex);
+ m_prefabFocusPublicInterface->FocusOnPathIndex(m_editorEntityContextId, linkIndex);
}
);
@@ -54,9 +54,9 @@ namespace AzToolsFramework::Prefab
connect(m_backButton, &QToolButton::clicked, this,
[&]()
{
- if (int length = m_prefabFocusInterface->GetPrefabFocusPathLength(m_editorEntityContextId); length > 1)
+ if (int length = m_prefabFocusPublicInterface->GetPrefabFocusPathLength(m_editorEntityContextId); length > 1)
{
- m_prefabFocusInterface->FocusOnPathIndex(m_editorEntityContextId, length - 2);
+ m_prefabFocusPublicInterface->FocusOnPathIndex(m_editorEntityContextId, length - 2);
}
}
);
@@ -65,7 +65,7 @@ namespace AzToolsFramework::Prefab
void PrefabViewportFocusPathHandler::OnPrefabFocusChanged()
{
// Push new Path
- m_breadcrumbsWidget->pushPath(m_prefabFocusInterface->GetPrefabFocusPath(m_editorEntityContextId).c_str());
+ m_breadcrumbsWidget->pushPath(m_prefabFocusPublicInterface->GetPrefabFocusPath(m_editorEntityContextId).c_str());
}
} // namespace AzToolsFramework::Prefab
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.h
index ce7744fb1b..a97db60e34 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.h
@@ -19,7 +19,7 @@
namespace AzToolsFramework::Prefab
{
- class PrefabFocusInterface;
+ class PrefabFocusPublicInterface;
class PrefabViewportFocusPathHandler
: public PrefabFocusNotificationBus::Handler
@@ -40,6 +40,6 @@ namespace AzToolsFramework::Prefab
AzFramework::EntityContextId m_editorEntityContextId = AzFramework::EntityContextId::CreateNull();
- PrefabFocusInterface* m_prefabFocusInterface = nullptr;
+ PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr;
};
} // namespace AzToolsFramework::Prefab
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp
index ba84e662c1..7f3b9e61fd 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp
@@ -28,6 +28,9 @@ AZ_PUSH_DISABLE_WARNING(4244 4251, "-Wunknown-warning-option")
#include
#include
#include
+#include
+#include
+#include
AZ_POP_DISABLE_WARNING
#include
@@ -1230,6 +1233,16 @@ namespace AzToolsFramework
return m_showThumbnailDropDownButton;
}
+ void PropertyAssetCtrl::SetCustomThumbnailEnabled(bool enabled)
+ {
+ m_thumbnail->SetCustomThumbnailEnabled(enabled);
+ }
+
+ void PropertyAssetCtrl::SetCustomThumbnailPixmap(const QPixmap& pixmap)
+ {
+ m_thumbnail->SetCustomThumbnailPixmap(pixmap);
+ }
+
void PropertyAssetCtrl::SetThumbnailCallback(EditCallbackType* editNotifyCallback)
{
m_thumbnailCallback = editNotifyCallback;
@@ -1356,15 +1369,27 @@ namespace AzToolsFramework
GUI->SetClearNotifyCallback(nullptr);
}
}
- else if (attrib == AZ_CRC("BrowseIcon", 0x507d7a4f))
+ else if (attrib == AZ_CRC_CE("BrowseIcon"))
{
AZStd::string iconPath;
- attrValue->Read(iconPath);
-
- if (!iconPath.empty())
+ if (attrValue->Read(iconPath) && !iconPath.empty())
{
GUI->SetBrowseButtonIcon(QIcon(iconPath.c_str()));
}
+ else
+ {
+ // A QPixmap object can't be assigned directly via an attribute.
+ // This allows dynamic icon data to be supplied as a buffer containing a serialized QPixmap.
+ AZStd::vector pixmapBuffer;
+ if (attrValue->Read>(pixmapBuffer) && !pixmapBuffer.empty())
+ {
+ QByteArray pixmapBytes(pixmapBuffer.data(), aznumeric_cast(pixmapBuffer.size()));
+ QDataStream stream(&pixmapBytes, QIODevice::ReadOnly);
+ QPixmap pixmap;
+ stream >> pixmap;
+ GUI->SetBrowseButtonIcon(pixmap);
+ }
+ }
}
else if (attrib == AZ_CRC_CE("BrowseButtonEnabled"))
{
@@ -1390,6 +1415,30 @@ namespace AzToolsFramework
GUI->SetShowThumbnail(showThumbnail);
}
}
+ else if (attrib == AZ_CRC_CE("ThumbnailIcon"))
+ {
+ AZStd::string iconPath;
+ if (attrValue->Read(iconPath) && !iconPath.empty())
+ {
+ GUI->SetCustomThumbnailEnabled(true);
+ GUI->SetCustomThumbnailPixmap(QPixmap::fromImage(QImage(iconPath.c_str())));
+ }
+ else
+ {
+ // A QPixmap object can't be assigned directly via an attribute.
+ // This allows dynamic icon data to be supplied as a buffer containing a serialized QPixmap.
+ AZStd::vector pixmapBuffer;
+ if (attrValue->Read>(pixmapBuffer) && !pixmapBuffer.empty())
+ {
+ QByteArray pixmapBytes(pixmapBuffer.data(), aznumeric_cast(pixmapBuffer.size()));
+ QDataStream stream(&pixmapBytes, QIODevice::ReadOnly);
+ QPixmap pixmap;
+ stream >> pixmap;
+ GUI->SetCustomThumbnailEnabled(true);
+ GUI->SetCustomThumbnailPixmap(pixmap);
+ }
+ }
+ }
else if (attrib == AZ_CRC_CE("ThumbnailCallback"))
{
PropertyAssetCtrl::EditCallbackType* func = azdynamic_cast(attrValue->GetAttribute());
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx
index cc4aff5649..0b98278bc5 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx
@@ -217,12 +217,17 @@ namespace AzToolsFramework
void SetHideProductFilesInAssetPicker(bool hide);
bool GetHideProductFilesInAssetPicker() const;
+ // Enable and configure a thumbnail widget that displays an asset preview and dropdown arrow for a dropdown menu
void SetShowThumbnail(bool enable);
bool GetShowThumbnail() const;
void SetShowThumbnailDropDownButton(bool enable);
bool GetShowThumbnailDropDownButton() const;
void SetThumbnailCallback(EditCallbackType* editNotifyCallback);
+ // If enabled, replaces the thumbnail widget content with a custom pixmap
+ void SetCustomThumbnailEnabled(bool enabled);
+ void SetCustomThumbnailPixmap(const QPixmap& pixmap);
+
void SetSelectedAssetID(const AZ::Data::AssetId& newID);
void SetCurrentAssetType(const AZ::Data::AssetType& newType);
void SetSelectedAssetID(const AZ::Data::AssetId& newID, const AZ::Data::AssetType& newType);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h
index eda8b482a1..01675e0044 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h
@@ -38,7 +38,7 @@ namespace AzToolsFramework
static bool UnsignedToolTip(QWidget* widget, QString& toolTipString);
};
- //! Base class for integer widget handlers to provide functionality independant
+ //! Base class for integer widget handlers to provide functionality independent
//! of widget type.
//! @tparam ValueType The integer primitive type of the handler.
//! @tparam PropertyControl The widget type of the handler.
@@ -167,8 +167,7 @@ namespace AzToolsFramework
PropertyControl* newCtrl = aznew PropertyControl(pParent);
this->connect(newCtrl, &PropertyControl::valueChanged, this, [newCtrl]()
{
- EBUS_EVENT(PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl);
- AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&PropertyEditorGUIMessages::Bus::Handler::RequestWrite, newCtrl);
+ AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&PropertyEditorGUIMessages::Bus::Events::RequestWrite, newCtrl);
});
// note: Qt automatically disconnects objects from each other when either end is destroyed, no need to worry about delete.
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntSpinCtrl.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntSpinCtrl.hxx
index 1e1e6a9592..fef4639a9f 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntSpinCtrl.hxx
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntSpinCtrl.hxx
@@ -98,11 +98,6 @@ namespace AzToolsFramework
QWidget* IntSpinBoxHandler::CreateGUI(QWidget* parent)
{
PropertyIntSpinCtrl* newCtrl = static_cast(BaseHandler::CreateGUI(parent));
- this->connect(newCtrl, &PropertyIntSpinCtrl::valueChanged, [newCtrl]()
- {
- AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&PropertyEditorGUIMessages::Bus::Handler::RequestWrite, newCtrl);
- });
-
return newCtrl;
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.cpp
index c458f7c47e..d8ddee6b76 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.cpp
@@ -7,75 +7,117 @@
*/
#include
-AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // 4251: 'QRawFont::d': class 'QExplicitlySharedDataPointer' needs to have dll-interface to be used by clients of class 'QRawFont'
- // 4800: 'QTextEngine *const ': forcing value to bool 'true' or 'false' (performance warning)
-#include
-#include
-#include
-#include
-#include
-#include
+
+// 4251: 'QRawFont::d': class 'QExplicitlySharedDataPointer' needs to have dll-interface to be used by clients of class
+// 'QRawFont' 4800: 'QTextEngine *const ': forcing value to bool 'true' or 'false' (performance warning)
+AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option")
#include
+#include
+#include
+#include
+#include
+#include
+#include
AZ_POP_DISABLE_WARNING
#include "ThumbnailPropertyCtrl.h"
namespace AzToolsFramework
{
-
ThumbnailPropertyCtrl::ThumbnailPropertyCtrl(QWidget* parent)
: QWidget(parent)
{
- QHBoxLayout* pLayout = new QHBoxLayout();
- pLayout->setContentsMargins(0, 0, 0, 0);
- pLayout->setSpacing(0);
-
m_thumbnail = new Thumbnailer::ThumbnailWidget(this);
m_thumbnail->setFixedSize(QSize(24, 24));
+ m_thumbnailEnlarged = new Thumbnailer::ThumbnailWidget(this);
+ m_thumbnailEnlarged->setFixedSize(QSize(180, 180));
+ m_thumbnailEnlarged->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
+
+ m_customThumbnail = new QLabel(this);
+ m_customThumbnail->setFixedSize(QSize(24, 24));
+ m_customThumbnail->setScaledContents(true);
+
+ m_customThumbnailEnlarged = new QLabel(this);
+ m_customThumbnailEnlarged->setFixedSize(QSize(180, 180));
+ m_customThumbnailEnlarged->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
+ m_customThumbnailEnlarged->setScaledContents(true);
+
m_dropDownArrow = new AspectRatioAwarePixmapWidget(this);
m_dropDownArrow->setPixmap(QPixmap(":/stylesheet/img/triangle0.png"));
m_dropDownArrow->setFixedSize(QSize(8, 24));
- ShowDropDownArrow(false);
m_emptyThumbnail = new QLabel(this);
m_emptyThumbnail->setPixmap(QPixmap(":/stylesheet/img/line.png"));
m_emptyThumbnail->setFixedSize(QSize(24, 24));
- pLayout->addWidget(m_emptyThumbnail);
+ QHBoxLayout* pLayout = new QHBoxLayout();
+ pLayout->setContentsMargins(0, 0, 0, 0);
+ pLayout->setSpacing(0);
pLayout->addWidget(m_thumbnail);
+ pLayout->addWidget(m_customThumbnail);
+ pLayout->addWidget(m_emptyThumbnail);
pLayout->addSpacing(4);
pLayout->addWidget(m_dropDownArrow);
pLayout->addSpacing(4);
-
setLayout(pLayout);
+
+ ShowDropDownArrow(false);
+ UpdateVisibility();
}
void ThumbnailPropertyCtrl::SetThumbnailKey(Thumbnailer::SharedThumbnailKey key, const char* contextName)
{
- m_key = key;
- m_emptyThumbnail->setVisible(false);
- m_thumbnail->SetThumbnailKey(key, contextName);
+ if (m_customThumbnailEnabled)
+ {
+ ClearThumbnail();
+ }
+ else
+ {
+ m_key = key;
+ m_thumbnail->SetThumbnailKey(m_key, contextName);
+ m_thumbnailEnlarged->SetThumbnailKey(m_key, contextName);
+ }
+ UpdateVisibility();
}
void ThumbnailPropertyCtrl::ClearThumbnail()
{
- m_emptyThumbnail->setVisible(true);
+ m_key.clear();
m_thumbnail->ClearThumbnail();
+ m_thumbnailEnlarged->ClearThumbnail();
+ UpdateVisibility();
}
void ThumbnailPropertyCtrl::ShowDropDownArrow(bool visible)
{
- if (visible)
- {
- setFixedSize(QSize(40, 24));
- }
- else
- {
- setFixedSize(QSize(24, 24));
- }
+ setFixedSize(QSize(visible ? 40 : 24, 24));
m_dropDownArrow->setVisible(visible);
}
+ void ThumbnailPropertyCtrl::SetCustomThumbnailEnabled(bool enabled)
+ {
+ m_customThumbnailEnabled = enabled;
+ UpdateVisibility();
+ }
+
+ void ThumbnailPropertyCtrl::SetCustomThumbnailPixmap(const QPixmap& pixmap)
+ {
+ m_customThumbnail->setPixmap(pixmap);
+ m_customThumbnailEnlarged->setPixmap(pixmap);
+ UpdateVisibility();
+ }
+
+ void ThumbnailPropertyCtrl::UpdateVisibility()
+ {
+ m_thumbnail->setVisible(m_key && !m_customThumbnailEnabled);
+ m_thumbnailEnlarged->setVisible(false);
+
+ m_customThumbnail->setVisible(m_customThumbnailEnabled);
+ m_customThumbnailEnlarged->setVisible(false);
+
+ m_emptyThumbnail->setVisible(!m_key && !m_customThumbnailEnabled);
+ }
+
bool ThumbnailPropertyCtrl::event(QEvent* e)
{
if (isEnabled())
@@ -83,7 +125,7 @@ namespace AzToolsFramework
if (e->type() == QEvent::MouseButtonPress)
{
emit clicked();
- return true; //ignore
+ return true; // ignore
}
}
@@ -94,37 +136,32 @@ namespace AzToolsFramework
{
QPainter p(this);
QRect targetRect(QPoint(), QSize(40, 24));
- p.fillRect(targetRect, QColor(17, 17, 17)); // #111111
+ p.fillRect(targetRect, QColor("#111111"));
QWidget::paintEvent(e);
}
void ThumbnailPropertyCtrl::enterEvent(QEvent* e)
{
m_dropDownArrow->setPixmap(QPixmap(":/stylesheet/img/triangle0_highlighted.png"));
- if (!m_thumbnailEnlarged && m_key)
- {
- QPoint position = mapToGlobal(pos() - QPoint(185, 0));
- QSize size(180, 180);
- m_thumbnailEnlarged.reset(new Thumbnailer::ThumbnailWidget());
- m_thumbnailEnlarged->setFixedSize(size);
- m_thumbnailEnlarged->move(position);
- m_thumbnailEnlarged->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
- m_thumbnailEnlarged->SetThumbnailKey(m_key);
- m_thumbnailEnlarged->raise();
- m_thumbnailEnlarged->show();
- }
+ const QPoint offset(-m_thumbnailEnlarged->width() - 5, -m_thumbnailEnlarged->height() / 2 + m_thumbnail->height() / 2);
+
+ m_thumbnailEnlarged->move(mapToGlobal(pos()) + offset);
+ m_thumbnailEnlarged->raise();
+ m_thumbnailEnlarged->setVisible(m_key && !m_customThumbnailEnabled);
+
+ m_customThumbnailEnlarged->move(mapToGlobal(pos()) + offset);
+ m_customThumbnailEnlarged->raise();
+ m_customThumbnailEnlarged->setVisible(m_customThumbnailEnabled);
QWidget::enterEvent(e);
}
void ThumbnailPropertyCtrl::leaveEvent(QEvent* e)
{
m_dropDownArrow->setPixmap(QPixmap(":/stylesheet/img/triangle0.png"));
- if (m_thumbnailEnlarged)
- {
- m_thumbnailEnlarged.reset();
- }
+ m_thumbnailEnlarged->setVisible(false);
+ m_customThumbnailEnlarged->setVisible(false);
QWidget::leaveEvent(e);
}
-}
+} // namespace AzToolsFramework
#include "UI/PropertyEditor/moc_ThumbnailPropertyCtrl.cpp"
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.h
index 93f703c4c5..ffd8234190 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.h
@@ -1,5 +1,3 @@
-#pragma once
-
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
@@ -8,6 +6,8 @@
*
*/
+#pragma once
+
#if !defined(Q_MOC_RUN)
#include
#include
@@ -35,25 +35,38 @@ namespace AzToolsFramework
//! Call this to set what thumbnail widget will display
void SetThumbnailKey(Thumbnailer::SharedThumbnailKey key, const char* contextName = "Default");
+
//! Remove current thumbnail
void ClearThumbnail();
+ //! Display a clickable dropdown arrow next to the thumbnail
void ShowDropDownArrow(bool visible);
- bool event(QEvent* e) override;
+ //! Override the thumbnail widget with a custom image
+ void SetCustomThumbnailEnabled(bool enabled);
+
+ //! Assign a custom image to display in place of thumbnail
+ void SetCustomThumbnailPixmap(const QPixmap& pixmap);
Q_SIGNALS:
void clicked();
- protected:
+ private:
+ void UpdateVisibility();
+
+ bool event(QEvent* e) override;
void paintEvent(QPaintEvent* e) override;
void enterEvent(QEvent* e) override;
void leaveEvent(QEvent* e) override;
- private:
Thumbnailer::SharedThumbnailKey m_key;
Thumbnailer::ThumbnailWidget* m_thumbnail = nullptr;
- QScopedPointer m_thumbnailEnlarged;
+ Thumbnailer::ThumbnailWidget* m_thumbnailEnlarged = nullptr;
+
+ QLabel* m_customThumbnail = nullptr;
+ QLabel* m_customThumbnailEnlarged = nullptr;
+ bool m_customThumbnailEnabled = false;
+
QLabel* m_emptyThumbnail = nullptr;
AspectRatioAwarePixmapWidget* m_dropDownArrow = nullptr;
};
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp
index 3ce350287f..bb718d0dc9 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp
@@ -187,15 +187,14 @@ namespace AzToolsFramework
}
// Verify if the entity Id corresponds to an entity that is focused; if not, halt selection.
- if (!m_focusModeInterface->IsInFocusSubTree(entityIdUnderCursor))
+ if (!IsSelectableAccordingToFocusMode(entityIdUnderCursor))
{
return AZ::EntityId();
}
// Container Entity support - if the entity that is being selected is part of a closed container,
// change the selection to the container instead.
- ContainerEntityInterface* containerEntityInterface = AZ::Interface::Get();
- if (containerEntityInterface)
+ if (ContainerEntityInterface* containerEntityInterface = AZ::Interface::Get())
{
return containerEntityInterface->FindHighestSelectableEntity(entityIdUnderCursor);
}
@@ -217,7 +216,7 @@ namespace AzToolsFramework
{
const AZ::EntityId entityId = m_entityDataCache->GetVisibleEntityId(entityCacheIndex);
- if (!m_entityDataCache->IsVisibleEntityVisible(entityCacheIndex))
+ if (!m_entityDataCache->IsVisibleEntityVisible(entityCacheIndex) || !IsSelectableInViewport(entityId))
{
continue;
}
@@ -263,4 +262,24 @@ namespace AzToolsFramework
}
}
}
+
+ bool EditorHelpers::IsSelectableInViewport(AZ::EntityId entityId)
+ {
+ return IsSelectableAccordingToFocusMode(entityId) && IsSelectableAccordingToContainerEntities(entityId);
+ }
+
+ bool EditorHelpers::IsSelectableAccordingToFocusMode(AZ::EntityId entityId)
+ {
+ return m_focusModeInterface->IsInFocusSubTree(entityId);
+ }
+
+ bool EditorHelpers::IsSelectableAccordingToContainerEntities(AZ::EntityId entityId)
+ {
+ if (ContainerEntityInterface* containerEntityInterface = AZ::Interface::Get())
+ {
+ return !containerEntityInterface->IsUnderClosedContainerEntity(entityId);
+ }
+
+ return true;
+ }
} // namespace AzToolsFramework
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.h
index a6a78a4e61..909a231635 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.h
@@ -58,7 +58,19 @@ namespace AzToolsFramework
AzFramework::DebugDisplayRequests& debugDisplay,
const AZStd::function& showIconCheck);
+ //! Returns whether the entityId can be selected in the viewport according
+ //! to the current Editor Focus Mode and Container Entity setup.
+ bool IsSelectableInViewport(AZ::EntityId entityId);
+
private:
+ //! Returns whether the entityId can be selected in the viewport according
+ //! to the current Editor Focus Mode setup.
+ bool IsSelectableAccordingToFocusMode(AZ::EntityId entityId);
+
+ //! Returns whether the entityId can be selected in the viewport according
+ //! to the current Container Entityu setup.
+ bool IsSelectableAccordingToContainerEntities(AZ::EntityId entityId);
+
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< Entity Data queried by the EditorHelpers.
const FocusModeInterface* m_focusModeInterface = nullptr;
};
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp
index 7015a25ce1..6ee5c97636 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp
@@ -1113,7 +1113,7 @@ namespace AzToolsFramework
});
m_boxSelect.InstallLeftMouseUp(
- [this, entityBoxSelectData]()
+ [this, entityBoxSelectData]
{
entityBoxSelectData->m_boxSelectSelectionCommand->UpdateSelection(EntityIdVectorFromContainer(m_selectedEntityIds));
@@ -2171,7 +2171,7 @@ namespace AzToolsFramework
// lock selection
AddAction(
m_actions, { QKeySequence(Qt::Key_L) }, LockSelection, LockSelectionTitle, LockSelectionDesc,
- [lockUnlock]()
+ [lockUnlock]
{
lockUnlock(true);
});
@@ -2179,7 +2179,7 @@ namespace AzToolsFramework
// unlock selection
AddAction(
m_actions, { QKeySequence(Qt::CTRL + Qt::Key_L) }, UnlockSelection, LockSelectionTitle, LockSelectionDesc,
- [lockUnlock]()
+ [lockUnlock]
{
lockUnlock(false);
});
@@ -2209,7 +2209,7 @@ namespace AzToolsFramework
// hide selection
AddAction(
m_actions, { QKeySequence(Qt::Key_H) }, HideSelection, HideSelectionTitle, HideSelectionDesc,
- [showHide]()
+ [showHide]
{
showHide(false);
});
@@ -2217,7 +2217,7 @@ namespace AzToolsFramework
// show selection
AddAction(
m_actions, { QKeySequence(Qt::CTRL + Qt::Key_H) }, ShowSelection, HideSelectionTitle, HideSelectionDesc,
- [showHide]()
+ [showHide]
{
showHide(true);
});
@@ -2225,7 +2225,7 @@ namespace AzToolsFramework
// unlock all entities in the level/scene
AddAction(
m_actions, { QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_L) }, UnlockAll, UnlockAllTitle, UnlockAllDesc,
- []()
+ []
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
@@ -2242,14 +2242,14 @@ namespace AzToolsFramework
// show all entities in the level/scene
AddAction(
m_actions, { QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_H) }, ShowAll, ShowAllTitle, ShowAllDesc,
- []()
+ []
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
ScopedUndoBatch undoBatch(ShowAllEntitiesUndoRedoDesc);
EnumerateEditorEntities(
- [](AZ::EntityId entityId)
+ [](const AZ::EntityId entityId)
{
ScopedUndoBatch::MarkEntityDirty(entityId);
SetEntityVisibility(entityId, true);
@@ -2259,7 +2259,7 @@ namespace AzToolsFramework
// select all entities in the level/scene
AddAction(
m_actions, { QKeySequence(Qt::CTRL + Qt::Key_A) }, SelectAll, SelectAllTitle, SelectAllDesc,
- [this]()
+ [this]
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
@@ -2299,7 +2299,7 @@ namespace AzToolsFramework
// invert current selection
AddAction(
m_actions, { QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_I) }, InvertSelect, InvertSelectionTitle, InvertSelectionDesc,
- [this]()
+ [this]
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
@@ -2346,17 +2346,10 @@ namespace AzToolsFramework
// duplicate selection
AddAction(
m_actions, { QKeySequence(Qt::CTRL + Qt::Key_D) }, DuplicateSelect, DuplicateTitle, DuplicateDesc,
- []()
+ []
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
- // Clear Widget selection - Prevents issues caused by cloning entities while a property in the Reflected Property Editor
- // is being edited.
- if (QApplication::focusWidget())
- {
- QApplication::focusWidget()->clearFocus();
- }
-
ScopedUndoBatch undoBatch(DuplicateUndoRedoDesc);
auto selectionCommand = AZStd::make_unique(EntityIdList(), DuplicateUndoRedoDesc);
selectionCommand->SetParent(undoBatch.GetUndoBatch());
@@ -2371,7 +2364,7 @@ namespace AzToolsFramework
// delete selection
AddAction(
m_actions, { QKeySequence(Qt::Key_Delete) }, DeleteSelect, DeleteTitle, DeleteDesc,
- [this]()
+ [this]
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
@@ -2388,21 +2381,21 @@ namespace AzToolsFramework
AddAction(
m_actions, { QKeySequence(Qt::Key_Space) }, EditEscaspe, "", "",
- [this]()
+ [this]
{
DeselectEntities();
});
AddAction(
m_actions, { QKeySequence(Qt::Key_P) }, EditPivot, TogglePivotTitleEditMenu, TogglePivotDesc,
- [this]()
+ [this]
{
ToggleCenterPivotSelection();
});
AddAction(
m_actions, { QKeySequence(Qt::Key_R) }, EditReset, ResetEntityTransformTitle, ResetEntityTransformDesc,
- [this]()
+ [this]
{
switch (m_mode)
{
@@ -2427,7 +2420,7 @@ namespace AzToolsFramework
AddAction(
m_actions, { QKeySequence(Qt::Key_U) }, ViewportUiVisible, "Toggle Viewport UI", "Hide/Show Viewport UI",
- [this]()
+ [this]
{
SetAllViewportUiVisible(!m_viewportUiVisible);
});
@@ -3236,7 +3229,7 @@ namespace AzToolsFramework
QAction* action = menu->addAction(QObject::tr(TogglePivotTitleRightClick));
QObject::connect(
action, &QAction::triggered, action,
- [this]()
+ [this]
{
ToggleCenterPivotSelection();
});
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake
index 37559564db..8dec7ab611 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake
@@ -646,6 +646,9 @@ set(FILES
Prefab/PrefabFocusHandler.cpp
Prefab/PrefabFocusInterface.h
Prefab/PrefabFocusNotificationBus.h
+ Prefab/PrefabFocusPublicInterface.h
+ Prefab/PrefabFocusUndo.h
+ Prefab/PrefabFocusUndo.cpp
Prefab/PrefabIdTypes.h
Prefab/PrefabLoader.h
Prefab/PrefabLoader.cpp
diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp
new file mode 100644
index 0000000000..a47e41da42
--- /dev/null
+++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+
+namespace AzToolsFramework
+{
+ TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithNoContainers)
+ {
+ // When no containers are in the way, the function will just return the entityId of the entity that was clicked.
+
+ // Click on Car Entity
+ ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
+
+ // Verify the correct entity is selected
+ auto selectedEntitiesAfter = GetSelectedEntities();
+ EXPECT_EQ(selectedEntitiesAfter.size(), 1);
+ EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]);
+ }
+
+ TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithClosedContainer)
+ {
+ // If a closed container is an ancestor of the queried entity, the closed container is selected.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); // Containers are closed by default
+
+ // Click on Car Entity
+ ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
+
+ // Verify the correct entity is selected
+ auto selectedEntitiesAfter = GetSelectedEntities();
+ EXPECT_EQ(selectedEntitiesAfter.size(), 1);
+ EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[StreetEntityName]);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ }
+
+ TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithOpenContainer)
+ {
+ // If a closed container is an ancestor of the queried entity, the closed container is selected.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
+
+ // Click on Car Entity
+ ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
+
+ // Verify the correct entity is selected
+ auto selectedEntitiesAfter = GetSelectedEntities();
+ EXPECT_EQ(selectedEntitiesAfter.size(), 1);
+ EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ }
+
+ TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithMultipleClosedContainers)
+ {
+ // If multiple closed containers are ancestors of the queried entity, the highest closed container is selected.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
+
+ // Click on Car Entity
+ ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
+
+ // Verify the correct entity is selected
+ auto selectedEntitiesAfter = GetSelectedEntities();
+ EXPECT_EQ(selectedEntitiesAfter.size(), 1);
+ EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CityEntityName]);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
+ }
+
+ TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithMultipleContainers)
+ {
+ // If multiple containers are ancestors of the queried entity, the highest closed container is selected.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
+ m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true);
+
+ // Click on Car Entity
+ ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
+
+ // Verify the correct entity is selected
+ auto selectedEntitiesAfter = GetSelectedEntities();
+ EXPECT_EQ(selectedEntitiesAfter.size(), 1);
+ EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[StreetEntityName]);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
+ }
+}
diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntityTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntityTests.cpp
new file mode 100644
index 0000000000..031062f027
--- /dev/null
+++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntityTests.cpp
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+
+namespace AzToolsFramework
+{
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_Register)
+ {
+ // Registering an entity is successful.
+ auto outcome = m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]);
+ EXPECT_TRUE(outcome.IsSuccess());
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_RegisterTwice)
+ {
+ // Registering an entity twice fails.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]);
+ auto outcome = m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]);
+ EXPECT_FALSE(outcome.IsSuccess());
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_Unregister)
+ {
+ // Unregistering a container entity is successful.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]);
+ auto outcome = m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
+ EXPECT_TRUE(outcome.IsSuccess());
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_UnregisterRegularEntity)
+ {
+ // Unregistering an entity that was not previously registered fails.
+ auto outcome = m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
+ EXPECT_FALSE(outcome.IsSuccess());
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_UnregisterTwice)
+ {
+ // Unregistering a container entity twice fails.
+ auto outcome = m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
+ EXPECT_FALSE(outcome.IsSuccess());
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOnRegularEntity)
+ {
+ // If a regular entity is passed, IsContainer returns false.
+ // Note that we use a different entity than the tests above to validate a completely new EntityId.
+ bool isContainer = m_containerEntityInterface->IsContainer(m_entityMap[SportsCarEntityName]);
+ EXPECT_FALSE(isContainer);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOnRegisteredContainer)
+ {
+ // If a container entity is passed, IsContainer returns true.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
+ bool isContainer = m_containerEntityInterface->IsContainer(m_entityMap[SportsCarEntityName]);
+ EXPECT_TRUE(isContainer);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOnUnRegisteredContainer)
+ {
+ // If an entity that was previously a container but was then unregistered is passed, IsContainer returns false.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
+
+ bool isContainer = m_containerEntityInterface->IsContainer(m_entityMap[SportsCarEntityName]);
+ EXPECT_FALSE(isContainer);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerOpenOnRegularEntity)
+ {
+ // Setting a regular entity to open should return a failure.
+ auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
+ EXPECT_FALSE(outcome.IsSuccess());
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerOpen)
+ {
+ // Set a container entity to open, and verify the operation was successful.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
+ EXPECT_TRUE(outcome.IsSuccess());
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerOpenTwice)
+ {
+ // Set a container entity to open twice, and verify that does not cause a failure (as intended).
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
+ auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
+ EXPECT_TRUE(outcome.IsSuccess());
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerClosed)
+ {
+ // Set a container entity to closed, and verify the operation was successful.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
+ EXPECT_TRUE(outcome.IsSuccess());
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnRegularEntity)
+ {
+ // Query open state on a regular entity, and verify it returns true.
+ // Open containers behave exactly as regular entities, so this is the expected return value.
+ bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]);
+ EXPECT_TRUE(isOpen);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnDefaultContainerEntity)
+ {
+ // Query open state on a newly registered container entity, and verify it returns false.
+ // Containers are registered closed by default.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
+ bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]);
+ EXPECT_FALSE(isOpen);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnOpenContainerEntity)
+ {
+ // Query open state on a container entity that was opened, and verify it returns true.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
+ m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true);
+ bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]);
+ EXPECT_TRUE(isOpen);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnClosedContainerEntity)
+ {
+ // Query open state on a container entity that was opened and then closed, and verify it returns false.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
+ m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true);
+ m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], false);
+ bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]);
+ EXPECT_FALSE(isOpen);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_ContainerOpenStateIsPreserved)
+ {
+ // Register an entity as container, open it, then unregister it.
+ // When the entity is registered again, the open state should be preserved.
+ // This behavior is necessary for the system to work alongside Prefab propagation refreshes.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
+ m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true);
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
+
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
+ bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]);
+ EXPECT_TRUE(isOpen);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearSucceeds)
+ {
+ // The Clear function works if no container is registered.
+ auto outcome = m_containerEntityInterface->Clear(m_editorEntityContextId);
+ EXPECT_TRUE(outcome.IsSuccess());
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearFailsIfContainersAreStillRegistered)
+ {
+ // The Clear function fails if a container is registered.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
+ auto outcome = m_containerEntityInterface->Clear(m_editorEntityContextId);
+ EXPECT_FALSE(outcome.IsSuccess());
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearSucceedsIfContainersAreUnregistered)
+ {
+ // The Clear function fails if a container is registered.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
+ auto outcome = m_containerEntityInterface->Clear(m_editorEntityContextId);
+ EXPECT_TRUE(outcome.IsSuccess());
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearDeletesPreservedOpenStates)
+ {
+ // Register an entity as container, open it, unregister it, then call clear.
+ // When the entity is registered again, the open state should not be preserved.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
+ m_containerEntityInterface->SetContainerOpen(m_entityMap[Passenger1EntityName], true);
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
+
+ m_containerEntityInterface->Clear(m_editorEntityContextId);
+
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
+ bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[Passenger1EntityName]);
+ EXPECT_FALSE(isOpen);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithNoContainers)
+ {
+ // When no containers are in the way, the function will just return the entityId that was passed to it.
+ AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]);
+ EXPECT_EQ(selectedEntityId, m_entityMap[Passenger2EntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithClosedContainer)
+ {
+ // If a closed container is an ancestor of the queried entity, the closed container is selected.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]); // Containers are closed by default
+ AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]);
+ EXPECT_EQ(selectedEntityId, m_entityMap[SportsCarEntityName]);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithOpenContainer)
+ {
+ // If an open container is an ancestor of the queried entity, it is ignored.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
+ m_containerEntityInterface->SetContainerOpen(m_entityMap[SportsCarEntityName], true);
+
+ AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]);
+ EXPECT_EQ(selectedEntityId, m_entityMap[Passenger2EntityName]);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithMultipleClosedContainers)
+ {
+ // If multiple closed containers are ancestors of the queried entity, the highest closed container is selected.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
+
+ AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]);
+ EXPECT_EQ(selectedEntityId, m_entityMap[StreetEntityName]);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
+ }
+
+ TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithMultipleContainers)
+ {
+ // If multiple containers are ancestors of the queried entity, the highest closed container is selected.
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
+ m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
+
+ AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]);
+ EXPECT_EQ(selectedEntityId, m_entityMap[SportsCarEntityName]);
+
+ // Restore default state for other tests.
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
+ m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
+ }
+
+}
diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp
index c309261a27..49bf7cee15 100644
--- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp
+++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp
@@ -14,6 +14,20 @@
namespace AzToolsFramework
{
+ void ClearSelectedEntities()
+ {
+ AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
+ &AzToolsFramework::ToolsApplicationRequestBus::Events::SetSelectedEntities, AzToolsFramework::EntityIdList());
+ }
+
+ AzToolsFramework::EntityIdList EditorFocusModeFixture::GetSelectedEntities()
+ {
+ AzToolsFramework::EntityIdList selectedEntities;
+ AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
+ selectedEntities, &AzToolsFramework::ToolsApplicationRequestBus::Events::GetSelectedEntities);
+ return selectedEntities;
+ }
+
void EditorFocusModeFixture::SetUpEditorFixtureImpl()
{
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
@@ -21,6 +35,9 @@ namespace AzToolsFramework
// in the unit tests.
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
+ m_containerEntityInterface = AZ::Interface::Get();
+ ASSERT_TRUE(m_containerEntityInterface != nullptr);
+
m_focusModeInterface = AZ::Interface::Get();
ASSERT_TRUE(m_focusModeInterface != nullptr);
@@ -31,6 +48,24 @@ namespace AzToolsFramework
m_editorEntityContextId, &AzToolsFramework::EditorEntityContextRequestBus::Events::GetEditorEntityContextId);
GenerateTestHierarchy();
+
+ // Clear the focus, disabling focus mode
+ m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
+
+ // Clear selection
+ ClearSelectedEntities();
+ }
+
+ void EditorFocusModeFixture::TearDownEditorFixtureImpl()
+ {
+ // Clear Container Entity preserved open states
+ m_containerEntityInterface->Clear(m_editorEntityContextId);
+
+ // Clear the focus, disabling focus mode
+ m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
+
+ // Clear selection
+ ClearSelectedEntities();
}
void EditorFocusModeFixture::GenerateTestHierarchy()
@@ -59,7 +94,7 @@ namespace AzToolsFramework
entity->Activate();
// Move the CarEntity so it's out of the way.
- AZ::TransformBus::Event(m_entityMap[CarEntityName], &AZ::TransformBus::Events::SetWorldTranslation, CarEntityPosition);
+ AZ::TransformBus::Event(m_entityMap[CarEntityName], &AZ::TransformBus::Events::SetWorldTranslation, WorldCarEntityPosition);
// Setup the camera so the Car entity is in view.
AzFramework::SetCameraTransform(
diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h
index f038408012..c48795a3a4 100644
--- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h
+++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h
@@ -14,6 +14,7 @@
#include
+#include
#include
#include
@@ -24,16 +25,20 @@ namespace AzToolsFramework
{
protected:
void SetUpEditorFixtureImpl() override;
+ void TearDownEditorFixtureImpl() override;
void GenerateTestHierarchy();
AZ::EntityId CreateEditorEntity(const char* name, AZ::EntityId parentId);
AZStd::unordered_map m_entityMap;
+
+ ContainerEntityInterface* m_containerEntityInterface = nullptr;
FocusModeInterface* m_focusModeInterface = nullptr;
public:
- AzFramework::EntityContextId m_editorEntityContextId = AzFramework::EntityContextId::CreateNull();
+ AzToolsFramework::EntityIdList GetSelectedEntities();
+ AzFramework::EntityContextId m_editorEntityContextId = AzFramework::EntityContextId::CreateNull();
AzFramework::CameraState m_cameraState;
inline static const AZ::Vector3 CameraPosition = AZ::Vector3(10.0f, 15.0f, 10.0f);
@@ -45,6 +50,7 @@ namespace AzToolsFramework
inline static const char* Passenger1EntityName = "Passenger1";
inline static const char* Passenger2EntityName = "Passenger2";
- inline static AZ::Vector3 CarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f);
+ inline static AZ::Vector3 WorldCarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f);
};
+
}
diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h
new file mode 100644
index 0000000000..4c9369bc46
--- /dev/null
+++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+namespace AzToolsFramework
+{
+ class EditorFocusModeSelectionFixture : public UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin
+ {
+ public:
+ void ClickAtWorldPositionOnViewport(const AZ::Vector3& worldPosition)
+ {
+ // Calculate the world position in screen space
+ const auto carScreenPosition = AzFramework::WorldToScreen(worldPosition, m_cameraState);
+
+ // Click the entity in the viewport
+ m_actionDispatcher->CameraState(m_cameraState)->MousePosition(carScreenPosition)->MouseLButtonDown()->MouseLButtonUp();
+ }
+ };
+} // namespace AzToolsFramework
diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp
index 968bb3f293..2f746c9d63 100644
--- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp
+++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp
@@ -6,64 +6,14 @@
*
*/
-#include
-
-#include
-#include
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
+#include
namespace AzToolsFramework
{
- class EditorFocusModeSelectionFixture
- : public UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin
- {
- public:
- void ClickAtWorldPositionOnViewport(const AZ::Vector3& worldPosition)
- {
- // Calculate the world position in screen space
- const auto carScreenPosition = AzFramework::WorldToScreen(worldPosition, m_cameraState);
-
- // Click the entity in the viewport
- m_actionDispatcher->CameraState(m_cameraState)->MousePosition(carScreenPosition)->MouseLButtonDown()->MouseLButtonUp();
- }
- };
-
- void ClearSelectedEntities()
- {
- AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
- &AzToolsFramework::ToolsApplicationRequestBus::Events::SetSelectedEntities, AzToolsFramework::EntityIdList());
- }
-
- AzToolsFramework::EntityIdList GetSelectedEntities()
- {
- AzToolsFramework::EntityIdList selectedEntities;
- AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
- selectedEntities, &AzToolsFramework::ToolsApplicationRequestBus::Events::GetSelectedEntities);
- return selectedEntities;
- }
-
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnLevel)
{
- // Clear the focus, disabling focus mode
- m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull());
- // Clear selection
- ClearSelectedEntities();
-
// Click on Car Entity
- ClickAtWorldPositionOnViewport(CarEntityPosition);
+ ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
@@ -75,73 +25,53 @@ namespace AzToolsFramework
{
// Set the focus on the Street Entity (parent of the test entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
- // Clear selection
- ClearSelectedEntities();
// Click on Car Entity
- ClickAtWorldPositionOnViewport(CarEntityPosition);
+ ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 1);
EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]);
-
- // Clear the focus, disabling focus mode
- m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull());
}
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnItself)
{
// Set the focus on the Car Entity (test entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]);
- // Clear selection
- ClearSelectedEntities();
// Click on Car Entity
- ClickAtWorldPositionOnViewport(CarEntityPosition);
+ ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 1);
EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]);
-
- // Clear the focus, disabling focus mode
- m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull());
}
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnSibling)
{
// Set the focus on the SportsCar Entity (sibling of the test entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[SportsCarEntityName]);
- // Clear selection
- ClearSelectedEntities();
// Click on Car Entity
- ClickAtWorldPositionOnViewport(CarEntityPosition);
+ ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 0);
-
- // Clear the focus, disabling focus mode
- m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull());
}
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnDescendant)
{
// Set the focus on the Passenger1 Entity (child of the entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger1EntityName]);
- // Clear selection
- ClearSelectedEntities();
// Click on Car Entity
- ClickAtWorldPositionOnViewport(CarEntityPosition);
+ ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
// Verify entity is selected
auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 0);
-
- // Clear the focus, disabling focus mode
- m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull());
}
}
diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeTests.cpp
index 22bc7a494c..eec3902f99 100644
--- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeTests.cpp
+++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeTests.cpp
@@ -33,55 +33,40 @@ namespace AzToolsFramework
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_AncestorsDescendants)
{
// When the focus is set to an entity, all its descendants are in the focus subtree while the ancestors aren't.
- {
- m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
+ m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
- }
-
- // Restore default expected focus.
- m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
}
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Siblings)
{
// If the root entity has siblings, they are also outside of the focus subtree.
- {
- m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]);
+ m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), false);
- }
-
- // Restore default expected focus.
- m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), false);
}
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Leaf)
{
// If the root is a leaf, then the focus subtree will consists of just that entity.
- {
- m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger2EntityName]);
+ m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger2EntityName]);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), false);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), false);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
- }
-
- // Restore default expected focus.
- m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), false);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), false);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
}
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Clear)
@@ -90,15 +75,13 @@ namespace AzToolsFramework
m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
// When the focus is cleared, the whole level is in the focus subtree; so we expect all entities to return true.
- {
- m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
+ m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), true);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true);
- EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
- }
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), true);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true);
+ EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
}
}
diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabFocus/PrefabFocusTests.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabFocus/PrefabFocusTests.cpp
index 72489b07a1..86c73e72e5 100644
--- a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabFocus/PrefabFocusTests.cpp
+++ b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabFocus/PrefabFocusTests.cpp
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
#include
namespace UnitTest
@@ -72,6 +73,9 @@ namespace UnitTest
m_prefabFocusInterface = AZ::Interface::Get();
ASSERT_TRUE(m_prefabFocusInterface != nullptr);
+ m_prefabFocusPublicInterface = AZ::Interface::Get();
+ ASSERT_TRUE(m_prefabFocusPublicInterface != nullptr);
+
AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult(
m_editorEntityContextId, &AzToolsFramework::EditorEntityContextRequestBus::Events::GetEditorEntityContextId);
@@ -91,6 +95,7 @@ namespace UnitTest
AZStd::unique_ptr m_rootInstance;
PrefabFocusInterface* m_prefabFocusInterface = nullptr;
+ PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr;
AzFramework::EntityContextId m_editorEntityContextId = AzFramework::EntityContextId::CreateNull();
inline static const char* CityEntityName = "City";
@@ -105,7 +110,7 @@ namespace UnitTest
{
// Verify FocusOnOwningPrefab works when passing the container entity of the root prefab.
{
- m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId());
+ m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId());
EXPECT_EQ(
m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId),
m_instanceMap[CityEntityName]->GetTemplateId());
@@ -120,7 +125,7 @@ namespace UnitTest
{
// Verify FocusOnOwningPrefab works when passing a nested entity of the root prefab.
{
- m_prefabFocusInterface->FocusOnOwningPrefab(m_entityMap[CityEntityName]->GetId());
+ m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_entityMap[CityEntityName]->GetId());
EXPECT_EQ(
m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId),
m_instanceMap[CityEntityName]->GetTemplateId());
@@ -135,7 +140,7 @@ namespace UnitTest
{
// Verify FocusOnOwningPrefab works when passing the container entity of a nested prefab.
{
- m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[CarEntityName]->GetContainerEntityId());
+ m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[CarEntityName]->GetContainerEntityId());
EXPECT_EQ(
m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId), m_instanceMap[CarEntityName]->GetTemplateId());
@@ -149,7 +154,7 @@ namespace UnitTest
{
// Verify FocusOnOwningPrefab works when passing a nested entity of the a nested prefab.
{
- m_prefabFocusInterface->FocusOnOwningPrefab(m_entityMap[Passenger1EntityName]->GetId());
+ m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_entityMap[Passenger1EntityName]->GetId());
EXPECT_EQ(
m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId), m_instanceMap[CarEntityName]->GetTemplateId());
@@ -169,7 +174,7 @@ namespace UnitTest
prefabEditorEntityOwnershipInterface->GetRootPrefabInstance();
EXPECT_TRUE(rootPrefabInstance.has_value());
- m_prefabFocusInterface->FocusOnOwningPrefab(AZ::EntityId());
+ m_prefabFocusPublicInterface->FocusOnOwningPrefab(AZ::EntityId());
EXPECT_EQ(
m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId), rootPrefabInstance->get().GetTemplateId());
@@ -183,10 +188,10 @@ namespace UnitTest
{
// Verify IsOwningPrefabBeingFocused returns true for all entities in a focused prefab (container/nested)
{
- m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId());
+ m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId());
- EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId()));
- EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId()));
+ EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId()));
+ EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId()));
}
}
@@ -194,13 +199,13 @@ namespace UnitTest
{
// Verify IsOwningPrefabBeingFocused returns false for all entities not in a focused prefab (ancestors/descendants)
{
- m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[StreetEntityName]->GetContainerEntityId());
+ m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[StreetEntityName]->GetContainerEntityId());
- EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[StreetEntityName]->GetContainerEntityId()));
- EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId()));
- EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId()));
- EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId()));
- EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId()));
+ EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[StreetEntityName]->GetContainerEntityId()));
+ EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId()));
+ EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId()));
+ EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId()));
+ EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId()));
}
}
@@ -208,12 +213,12 @@ namespace UnitTest
{
// Verify IsOwningPrefabBeingFocused returns false for all entities not in a focused prefab (siblings)
{
- m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[SportsCarEntityName]->GetContainerEntityId());
+ m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[SportsCarEntityName]->GetContainerEntityId());
- EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[SportsCarEntityName]->GetContainerEntityId()));
- EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger2EntityName]->GetId()));
- EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId()));
- EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId()));
+ EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[SportsCarEntityName]->GetContainerEntityId()));
+ EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger2EntityName]->GetId()));
+ EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId()));
+ EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId()));
}
}
diff --git a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake
index 87d522c4a6..ef6774f620 100644
--- a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake
+++ b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake
@@ -37,8 +37,11 @@ set(FILES
EntityTestbed.h
FileFunc.cpp
FingerprintingTests.cpp
+ FocusMode/ContainerEntitySelectionTests.cpp
+ FocusMode/ContainerEntityTests.cpp
FocusMode/EditorFocusModeFixture.cpp
FocusMode/EditorFocusModeFixture.h
+ FocusMode/EditorFocusModeSelectionFixture.h
FocusMode/EditorFocusModeSelectionTests.cpp
FocusMode/EditorFocusModeTests.cpp
GenericComponentWrapperTest.cpp
diff --git a/Code/Legacy/CryCommon/IMovieSystem.h b/Code/Legacy/CryCommon/IMovieSystem.h
index 6cc5a06c8f..4da08d3bbf 100644
--- a/Code/Legacy/CryCommon/IMovieSystem.h
+++ b/Code/Legacy/CryCommon/IMovieSystem.h
@@ -13,6 +13,7 @@
#include
#include
#include
+#include