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..381f266fab 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):
"""
@@ -146,7 +148,7 @@ class TestAllComponentsIndepthTests(object):
golden_image_path = os.path.join(golden_images_directory(), golden_image)
golden_images.append(golden_image_path)
- expected_lines = ["Light component tests completed."]
+ expected_lines = ["spot_light Controller|Configuration|Shadows|Shadowmap size: SUCCESS"]
unexpected_lines = [
"Trace::Assert",
"Trace::Error",
@@ -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_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py
index 31b4cb687d..447a4ebac9 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py
@@ -67,5 +67,9 @@ class TestAutomation(EditorTestSuite):
class AtomEditorComponents_PostFXLayerAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_PostFXLayerAdded as test_module
+ @pytest.mark.test_case_id("C36525665")
+ class AtomEditorComponents_PostFXShapeWeightModifierAdded(EditorSharedTest):
+ from Atom.tests import hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded as test_module
+
class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSharedTest):
from Atom.tests import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module
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
new file mode 100644
index 0000000000..4c98bcd130
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py
@@ -0,0 +1,207 @@
+"""
+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:
+ creation_undo = (
+ "UNDO Entity creation success",
+ "UNDO Entity creation failed")
+ creation_redo = (
+ "REDO Entity creation success",
+ "REDO Entity creation failed")
+ postfx_shape_weight_creation = (
+ "PostFx Shape Weight Modifier Entity successfully created",
+ "PostFx Shape Weight Modifier Entity failed to be created")
+ postfx_shape_weight_component = (
+ "Entity has a PostFx Shape Weight Modifier component",
+ "Entity failed to find PostFx Shape Weight Modifier component")
+ postfx_shape_weight_disabled = (
+ "PostFx Shape Weight Modifier component disabled",
+ "PostFx Shape Weight Modifier component was not disabled.")
+ postfx_layer_component = (
+ "Entity has a PostFX Layer component",
+ "Entity did not have an PostFX Layer component")
+ tube_shape_component = (
+ "Entity has a Tube Shape component",
+ "Entity did not have a Tube Shape component")
+ postfx_shape_weight_enabled = (
+ "PostFx Shape Weight Modifier component enabled",
+ "PostFx Shape Weight Modifier component was not enabled.")
+ enter_game_mode = (
+ "Entered game mode",
+ "Failed to enter game mode")
+ exit_game_mode = (
+ "Exited game mode",
+ "Couldn't exit game mode")
+ is_visible = (
+ "Entity is visible",
+ "Entity was not visible")
+ is_hidden = (
+ "Entity is hidden",
+ "Entity was not hidden")
+ entity_deleted = (
+ "Entity deleted",
+ "Entity was not deleted")
+ deletion_undo = (
+ "UNDO deletion success",
+ "UNDO deletion failed")
+ deletion_redo = (
+ "REDO deletion success",
+ "REDO deletion failed")
+
+
+def AtomEditorComponents_postfx_shape_weight_AddedToEntity():
+ """
+ Summary:
+ Tests the PostFx Shape Weight Modifier component can be added to an entity and has the expected functionality.
+
+ Test setup:
+ - Wait for Editor idle loop.
+ - Open the "Base" level.
+
+ Expected Behavior:
+ The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
+ Creation and deletion undo/redo should also work.
+
+ Test Steps:
+ 1) Create a PostFx Shape Weight Modifier entity with no components.
+ 2) Add a PostFx Shape Weight Modifier component to PostFx Shape Weight Modifier entity.
+ 3) UNDO the entity creation and component addition.
+ 4) REDO the entity creation and component addition.
+ 5) Verify PostFx Shape Weight Modifier component not enabled.
+ 6) Add PostFX Layer component since it is required by the PostFx Shape Weight Modifier component.
+ 7) Verify PostFx Shape Weight Modifier component is NOT enabled since it also requires a shape.
+ 8) Add a required shape looping over a list and checking if it enables PostFX Shape Weight Modifier.
+ 9) Undo to remove each added shape and verify PostFX Shape Weight Modifier is not enabled.
+ 10) Verify PostFx Shape Weight Modifier component is enabled by adding Spline and Tube Shape component.
+ 11) Enter/Exit game mode.
+ 12) Test IsHidden.
+ 13) Test IsVisible.
+ 14) Delete PostFx Shape Weight Modifier entity.
+ 15) UNDO deletion.
+ 16) REDO deletion.
+ 17) Look for errors.
+
+ :return: None
+ """
+
+ import azlmbr.legacy.general as general
+
+ from editor_python_test_tools.editor_entity_utils import EditorEntity
+ from editor_python_test_tools.utils import Report, Tracer, TestHelper
+
+ with Tracer() as error_tracer:
+ # Test setup begins.
+ # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
+ TestHelper.init_idle()
+ TestHelper.open_level("", "Base")
+
+ # Test steps begin.
+ # 1. Create a PostFx Shape Weight Modifier entity with no components.
+ postfx_shape_weight_name = "PostFX Shape Weight Modifier"
+ postfx_shape_weight_entity = EditorEntity.create_editor_entity(postfx_shape_weight_name)
+ Report.critical_result(Tests.postfx_shape_weight_creation, postfx_shape_weight_entity.exists())
+
+ # 2. Add a PostFx Shape Weight Modifier component to PostFx Shape Weight Modifier entity.
+ postfx_shape_weight_component = postfx_shape_weight_entity.add_component(postfx_shape_weight_name)
+ Report.critical_result(
+ Tests.postfx_shape_weight_component,
+ postfx_shape_weight_entity.has_component(postfx_shape_weight_name))
+
+ # 3. UNDO the entity creation and component addition.
+ # -> UNDO component addition.
+ general.undo()
+ # -> UNDO naming entity.
+ general.undo()
+ # -> UNDO selecting entity.
+ general.undo()
+ # -> UNDO entity creation.
+ general.undo()
+ general.idle_wait_frames(1)
+ Report.result(Tests.creation_undo, not postfx_shape_weight_entity.exists())
+
+ # 4. REDO the entity creation and component addition.
+ # -> REDO entity creation.
+ general.redo()
+ # -> REDO selecting entity.
+ general.redo()
+ # -> REDO naming entity.
+ general.redo()
+ # -> REDO component addition.
+ general.redo()
+ general.idle_wait_frames(1)
+ Report.result(Tests.creation_redo, postfx_shape_weight_entity.exists())
+
+ # 5. Verify PostFx Shape Weight Modifier component not enabled.
+ Report.result(Tests.postfx_shape_weight_disabled, not postfx_shape_weight_component.is_enabled())
+
+ # 6. Add PostFX Layer component since it is required by the PostFx Shape Weight Modifier component.
+ postfx_layer_name = "PostFX Layer"
+ postfx_shape_weight_entity.add_component(postfx_layer_name)
+ Report.result(Tests.postfx_layer_component, postfx_shape_weight_entity.has_component(postfx_layer_name))
+
+ # 7. Verify PostFx Shape Weight Modifier component is NOT enabled since it also requires a shape.
+ Report.result(Tests.postfx_shape_weight_disabled, not postfx_shape_weight_component.is_enabled())
+
+ # 8. Add a required shape looping over a list and checking if it enables PostFX Shape Weight Modifier.
+ for shape in ['Axis Aligned Box Shape', 'Box Shape', 'Capsule Shape', 'Compound Shape', 'Cylinder Shape',
+ 'Disk Shape', 'Polygon Prism Shape', 'Quad Shape', 'Sphere Shape', 'Vegetation Reference Shape']:
+ postfx_shape_weight_entity.add_component(shape)
+ test_shape = (
+ f"Entity has a {shape} component",
+ f"Entity did not have a {shape} component")
+ Report.result(test_shape, postfx_shape_weight_entity.has_component(shape))
+
+ # Check if required shape allows PostFX Shape Weight Modifier to be enabled
+ Report.result(Tests.postfx_shape_weight_enabled, postfx_shape_weight_component.is_enabled())
+
+ # 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.
+ postfx_shape_weight_entity.add_components(['Spline', 'Tube Shape'])
+ Report.result(Tests.tube_shape_component, postfx_shape_weight_entity.has_component('Tube Shape'))
+ Report.result(Tests.postfx_shape_weight_enabled, postfx_shape_weight_component.is_enabled())
+
+ # 11. Enter/Exit game mode.
+ TestHelper.enter_game_mode(Tests.enter_game_mode)
+ general.idle_wait_frames(1)
+ TestHelper.exit_game_mode(Tests.exit_game_mode)
+
+ # 12. Test IsHidden.
+ postfx_shape_weight_entity.set_visibility_state(False)
+ Report.result(Tests.is_hidden, postfx_shape_weight_entity.is_hidden() is True)
+
+ # 13. Test IsVisible.
+ postfx_shape_weight_entity.set_visibility_state(True)
+ general.idle_wait_frames(1)
+ Report.result(Tests.is_visible, postfx_shape_weight_entity.is_visible() is True)
+
+ # 14. Delete PostFx Shape Weight Modifier entity.
+ postfx_shape_weight_entity.delete()
+ Report.result(Tests.entity_deleted, not postfx_shape_weight_entity.exists())
+
+ # 15. UNDO deletion.
+ general.undo()
+ Report.result(Tests.deletion_undo, postfx_shape_weight_entity.exists())
+
+ # 16. REDO deletion.
+ general.redo()
+ Report.result(Tests.deletion_redo, not postfx_shape_weight_entity.exists())
+
+ # 17. Look for errors or asserts.
+ TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
+ for error_info in error_tracer.errors:
+ Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
+ for assert_info in error_tracer.asserts:
+ Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
+
+
+if __name__ == "__main__":
+ from editor_python_test_tools.utils import Report
+ Report.start_test(AtomEditorComponents_postfx_shape_weight_AddedToEntity)
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/AutomatedTesting/Objects/MorphTargets/DisplayWrinkleMaskBlendValues.material b/AutomatedTesting/Objects/MorphTargets/DisplayWrinkleMaskBlendValues.material
new file mode 100644
index 0000000000..878b3ac39f
--- /dev/null
+++ b/AutomatedTesting/Objects/MorphTargets/DisplayWrinkleMaskBlendValues.material
@@ -0,0 +1,13 @@
+{
+ "description": "",
+ "materialType": "Materials/Types/Skin.materialtype",
+ "parentMaterial": "",
+ "propertyLayoutVersion": 3,
+ "properties": {
+ "wrinkleLayers": {
+ "count": 3,
+ "enable": true,
+ "showBlendValues": true
+ }
+ }
+}
diff --git a/AutomatedTesting/Objects/MorphTargets/morphActor.fbx b/AutomatedTesting/Objects/MorphTargets/morphActor.fbx
new file mode 100644
index 0000000000..ffb75e680e
--- /dev/null
+++ b/AutomatedTesting/Objects/MorphTargets/morphActor.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:53e17ec8155911c8b42e85436130f600bd6dddd8931a8ccb1b2f8a9f8674cc85
+size 45104
diff --git a/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph1_wrinklemask.tif b/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph1_wrinklemask.tif
new file mode 100644
index 0000000000..3bc18cf450
--- /dev/null
+++ b/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph1_wrinklemask.tif
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0da56a05daa0ec1c476cfe25ca6d3b65267c98886cf33408f6e852fb325a8e2c
+size 198084
diff --git a/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph2_wriklemask.tif b/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph2_wriklemask.tif
new file mode 100644
index 0000000000..39e70f5acf
--- /dev/null
+++ b/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph2_wriklemask.tif
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e3537fbe9205731a242251c525a67bbb5f3b8f5307537f1dc0c318b5b885ce52
+size 198112
diff --git a/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph3_wrinklemask.tif b/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph3_wrinklemask.tif
new file mode 100644
index 0000000000..43e19f0d5f
--- /dev/null
+++ b/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph3_wrinklemask.tif
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bd794d5dd4b749c3275bfab79b9b5ae3f8e007d3e6741c0566c9c2d3931123bf
+size 198112
diff --git a/AutomatedTesting/Objects/MorphTargets/morphAnimation.fbx b/AutomatedTesting/Objects/MorphTargets/morphAnimation.fbx
new file mode 100644
index 0000000000..c0dcc007dc
--- /dev/null
+++ b/AutomatedTesting/Objects/MorphTargets/morphAnimation.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:45ded862987a64061deffd8e4c9aa1dff4eec3bcff5f7b505679f1959e8ae137
+size 51440
diff --git a/Code/Editor/CMakeLists.txt b/Code/Editor/CMakeLists.txt
index 2ea0aa1a74..bdfac373eb 100644
--- a/Code/Editor/CMakeLists.txt
+++ b/Code/Editor/CMakeLists.txt
@@ -102,7 +102,7 @@ ly_add_target(
3rdParty::Qt::Gui
3rdParty::Qt::Widgets
3rdParty::Qt::Concurrent
- 3rdParty::tiff
+ 3rdParty::TIFF
3rdParty::squish-ccr
3rdParty::AWSNativeSDK::STS
Legacy::CryCommon
diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp
index abba2bb9c6..4f2e995ac4 100644
--- a/Code/Editor/CryEdit.cpp
+++ b/Code/Editor/CryEdit.cpp
@@ -57,6 +57,7 @@ AZ_POP_DISABLE_WARNING
#include
#include
#include
+#include
// AzToolsFramework
#include
@@ -3021,6 +3022,15 @@ CCryEditApp::ECreateLevelResult CCryEditApp::CreateLevel(const QString& levelNam
bool bIsDocModified = GetIEditor()->GetDocument()->IsModified();
OnSwitchPhysics();
GetIEditor()->GetDocument()->SetModifiedFlag(bIsDocModified);
+
+ if (usePrefabSystemForLevels)
+ {
+ auto* rootSpawnableInterface = AzFramework::RootSpawnableInterface::Get();
+ if (rootSpawnableInterface)
+ {
+ rootSpawnableInterface->ProcessSpawnableQueue();
+ }
+ }
}
const QScopedValueRollback rollback(m_creatingNewLevel);
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/FileUtil.cpp b/Code/Editor/Util/FileUtil.cpp
index eeb6912acf..baca69d628 100644
--- a/Code/Editor/Util/FileUtil.cpp
+++ b/Code/Editor/Util/FileUtil.cpp
@@ -1195,7 +1195,7 @@ bool CFileUtil::IsFileExclusivelyAccessable(const QString& strFilePath)
//////////////////////////////////////////////////////////////////////////
bool CFileUtil::CreatePath(const QString& strPath)
{
-#if defined(AZ_PLATFORM_MAC)
+#if !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
bool pathCreated = true;
QString cleanPath = QDir::cleanPath(strPath);
@@ -1252,7 +1252,7 @@ bool CFileUtil::CreatePath(const QString& strPath)
}
return true;
-#endif
+#endif // !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
}
//////////////////////////////////////////////////////////////////////////
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/Math/IntersectSegment.cpp b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp
index a7a0d5197e..5d13acc34c 100644
--- a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp
+++ b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp
@@ -15,7 +15,7 @@ using namespace Intersect;
// IntersectSegmentTriangleCCW
// [10/21/2009]
//=========================================================================
-int Intersect::IntersectSegmentTriangleCCW(
+bool Intersect::IntersectSegmentTriangleCCW(
const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c,
/*float &u, float &v, float &w,*/ Vector3& normal, float& t)
{
@@ -34,7 +34,7 @@ int Intersect::IntersectSegmentTriangleCCW(
float d = qp.Dot(normal);
if (d <= 0.0f)
{
- return 0;
+ return false;
}
// Compute intersection t value of pq with plane of triangle. A ray
@@ -46,7 +46,7 @@ int Intersect::IntersectSegmentTriangleCCW(
// range segment check t[0,1] (it this case [0,d])
if (t < 0.0f || t > d)
{
- return 0;
+ return false;
}
// Compute barycentric coordinate components and test if within bounds
@@ -54,12 +54,12 @@ int Intersect::IntersectSegmentTriangleCCW(
v = ac.Dot(e);
if (v < 0.0f || v > d)
{
- return 0;
+ return false;
}
w = -ab.Dot(e);
if (w < 0.0f || v + w > d)
{
- return 0;
+ return false;
}
// Segment/ray intersects triangle. Perform delayed division and
@@ -72,14 +72,14 @@ int Intersect::IntersectSegmentTriangleCCW(
normal.Normalize();
- return 1;
+ return true;
}
//=========================================================================
// IntersectSegmentTriangle
// [10/21/2009]
//=========================================================================
-int
+bool
Intersect::IntersectSegmentTriangle(
const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c,
/*float &u, float &v, float &w,*/ Vector3& normal, float& t)
@@ -111,7 +111,7 @@ Intersect::IntersectSegmentTriangle(
// so either have a parallel ray or our normal is flipped
if (d >= -Constants::FloatEpsilon)
{
- return 0; // parallel
+ return false; // parallel
}
d = -d;
e = ap.Cross(qp);
@@ -125,19 +125,19 @@ Intersect::IntersectSegmentTriangle(
// range segment check t[0,1] (it this case [0,d])
if (t < 0.0f || t > d)
{
- return 0;
+ return false;
}
// Compute barycentric coordinate components and test if within bounds
v = ac.Dot(e);
if (v < 0.0f || v > d)
{
- return 0;
+ return false;
}
w = -ab.Dot(e);
if (w < 0.0f || v + w > d)
{
- return 0;
+ return false;
}
// Segment/ray intersects the triangle. Perform delayed division and
@@ -150,14 +150,14 @@ Intersect::IntersectSegmentTriangle(
normal.Normalize();
- return 1;
+ return true;
}
//=========================================================================
// TestSegmentAABBOrigin
// [10/21/2009]
//=========================================================================
-int
+bool
AZ::Intersect::TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& halfVector, const Vector3& aabbExtends)
{
const Vector3 EPSILON(0.001f); // \todo this is slow load move to a const
@@ -168,7 +168,7 @@ AZ::Intersect::TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& hal
// Try world coordinate axes as separating axes
if (!absMidpoint.IsLessEqualThan(absHalfMidpoint))
{
- return 0;
+ return false;
}
// Add in an epsilon term to counteract arithmetic errors when segment is
@@ -188,11 +188,11 @@ AZ::Intersect::TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& hal
Vector3 ead(ey * adz + ez * ady, ex * adz + ez * adx, ex * ady + ey * adx);
if (!absMDCross.IsLessEqualThan(ead))
{
- return 0;
+ return false;
}
// No separating axis found; segment must be overlapping AABB
- return 1;
+ return true;
}
@@ -200,7 +200,7 @@ AZ::Intersect::TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& hal
// IntersectRayAABB
// [10/21/2009]
//=========================================================================
-int
+RayAABBIsectTypes
AZ::Intersect::IntersectRayAABB(
const Vector3& rayStart, const Vector3& dir, const Vector3& dirRCP, const Aabb& aabb,
float& tStart, float& tEnd, Vector3& startNormal /*, Vector3& inter*/)
@@ -356,7 +356,7 @@ AZ::Intersect::IntersectRayAABB(
// IntersectRayAABB2
// [2/18/2011]
//=========================================================================
-int
+RayAABBIsectTypes
AZ::Intersect::IntersectRayAABB2(const Vector3& rayStart, const Vector3& dirRCP, const Aabb& aabb, float& start, float& end)
{
float tmin, tmax, tymin, tymax, tzmin, tzmax;
@@ -408,7 +408,7 @@ AZ::Intersect::IntersectRayAABB2(const Vector3& rayStart, const Vector3& dirRCP,
return ISECT_RAY_AABB_ISECT;
}
-int AZ::Intersect::IntersectRayDisk(
+bool AZ::Intersect::IntersectRayDisk(
const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& diskCenter, const float diskRadius, const Vector3& diskNormal, float& t)
{
// First intersect with the plane of the disk
@@ -421,10 +421,10 @@ int AZ::Intersect::IntersectRayDisk(
if (pointOnPlane.GetDistance(diskCenter) < diskRadius)
{
t = planeIntersectionDistance;
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
// Reference: Real-Time Collision Detection - 5.3.7 Intersecting Ray or Segment Against Cylinder, and the book's errata.
@@ -1012,7 +1012,7 @@ int AZ::Intersect::IntersectRayQuad(
}
// reference: Real-Time Collision Detection, 5.3.3 Intersecting Ray or Segment Against Box
-int AZ::Intersect::IntersectRayBox(
+bool AZ::Intersect::IntersectRayBox(
const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& boxCenter, const Vector3& boxAxis1,
const Vector3& boxAxis2, const Vector3& boxAxis3, float boxHalfExtent1, float boxHalfExtent2, float boxHalfExtent3, float& t)
{
@@ -1044,7 +1044,7 @@ int AZ::Intersect::IntersectRayBox(
// If the ray is parallel to the slab and the ray origin is outside, return no intersection.
if (tp < 0.0f || tn < 0.0f)
{
- return 0;
+ return false;
}
}
else
@@ -1065,7 +1065,7 @@ int AZ::Intersect::IntersectRayBox(
tmax = AZ::GetMin(tmax, t2);
if (tmin > tmax)
{
- return 0;
+ return false;
}
}
@@ -1085,7 +1085,7 @@ int AZ::Intersect::IntersectRayBox(
// If the ray is parallel to the slab and the ray origin is outside, return no intersection.
if (tp < 0.0f || tn < 0.0f)
{
- return 0;
+ return false;
}
}
else
@@ -1106,7 +1106,7 @@ int AZ::Intersect::IntersectRayBox(
tmax = AZ::GetMin(tmax, t2);
if (tmin > tmax)
{
- return 0;
+ return false;
}
}
@@ -1126,7 +1126,7 @@ int AZ::Intersect::IntersectRayBox(
// If the ray is parallel to the slab and the ray origin is outside, return no intersection.
if (tp < 0.0f || tn < 0.0f)
{
- return 0;
+ return false;
}
}
else
@@ -1147,15 +1147,15 @@ int AZ::Intersect::IntersectRayBox(
tmax = AZ::GetMin(tmax, t2);
if (tmin > tmax)
{
- return 0;
+ return false;
}
}
t = (isRayOriginInsideBox ? tmax : tmin);
- return 1;
+ return true;
}
-int AZ::Intersect::IntersectRayObb(const Vector3& rayOrigin, const Vector3& rayDir, const Obb& obb, float& t)
+bool AZ::Intersect::IntersectRayObb(const Vector3& rayOrigin, const Vector3& rayDir, const Obb& obb, float& t)
{
return AZ::Intersect::IntersectRayBox(rayOrigin, rayDir, obb.GetPosition(),
obb.GetAxisX(), obb.GetAxisY(), obb.GetAxisZ(),
@@ -1166,7 +1166,7 @@ int AZ::Intersect::IntersectRayObb(const Vector3& rayOrigin, const Vector3& rayD
// IntersectSegmentCylinder
// [10/21/2009]
//=========================================================================
-int
+CylinderIsectTypes
AZ::Intersect::IntersectSegmentCylinder(
const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t)
{
@@ -1225,7 +1225,7 @@ AZ::Intersect::IntersectSegmentCylinder(
return RR_ISECT_RAY_CYL_NONE; // No real roots; no intersection
}
t = (-b - Sqrt(discr)) / a;
- int result = RR_ISECT_RAY_CYL_PQ; // default along the PQ segment
+ CylinderIsectTypes result = RR_ISECT_RAY_CYL_PQ; // default along the PQ segment
if (md + t * nd < 0.0f)
{
@@ -1294,7 +1294,7 @@ AZ::Intersect::IntersectSegmentCylinder(
// IntersectSegmentCapsule
// [10/21/2009]
//=========================================================================
-int
+CapsuleIsectTypes
AZ::Intersect::IntersectSegmentCapsule(const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t)
{
int result = IntersectSegmentCylinder(sa, dir, p, q, r, t);
@@ -1361,13 +1361,13 @@ AZ::Intersect::IntersectSegmentCapsule(const Vector3& sa, const Vector3& dir, co
// IntersectSegmentPolyhedron
// [10/21/2009]
//=========================================================================
-int
+bool
AZ::Intersect::IntersectSegmentPolyhedron(
- const Vector3& sa, const Vector3& sBA, const Plane p[], int numPlanes,
+ const Vector3& sa, const Vector3& dir, const Plane p[], int numPlanes,
float& tfirst, float& tlast, int& iFirstPlane, int& iLastPlane)
{
// Compute direction vector for the segment
- Vector3 d = /*b - a*/ sBA;
+ Vector3 d = /*b - a*/ dir;
// Set initial interval to being the whole segment. For a ray, tlast should be
// set to +RR_FLT_MAX. For a line, additionally tfirst should be set to -RR_FLT_MAX
tfirst = 0.0f;
@@ -1388,7 +1388,7 @@ AZ::Intersect::IntersectSegmentPolyhedron(
// If so, return "no intersection" if segment lies outside plane
if (dist < 0.0f)
{
- return 0;
+ return false;
}
}
else
@@ -1417,7 +1417,7 @@ AZ::Intersect::IntersectSegmentPolyhedron(
// Exit with "no intersection" if intersection becomes empty
if (tfirst > tlast)
{
- return 0;
+ return false;
}
}
}
@@ -1425,11 +1425,11 @@ AZ::Intersect::IntersectSegmentPolyhedron(
//DBG_Assert(iFirstPlane!=-1&&iLastPlane!=-1,("We have some bad border case to have only one plane, fix this function!"));
if (iFirstPlane == -1 && iLastPlane == -1)
{
- return 0;
+ return false;
}
// A nonzero logical intersection, so the segment intersects the polyhedron
- return 1;
+ return true;
}
//=========================================================================
@@ -1442,7 +1442,7 @@ AZ::Intersect::ClosestSegmentSegment(
const Vector3& segment2Start, const Vector3& segment2End,
float& segment1Proportion, float& segment2Proportion,
Vector3& closestPointSegment1, Vector3& closestPointSegment2,
- float epsilon /*= 1e-4f*/ )
+ float epsilon)
{
const Vector3 segment1 = segment1End - segment1Start;
const Vector3 segment2 = segment2End - segment2Start;
diff --git a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h
index df3d5e10fb..523069987f 100644
--- a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h
+++ b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h
@@ -5,363 +5,398 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
-#ifndef AZCORE_MATH_SEGMENT_INTERSECTION_H
-#define AZCORE_MATH_SEGMENT_INTERSECTION_H
+#pragma once
-#include
#include
#include
#include
-
-/// \file isect_segment.h
+#include
namespace AZ
{
namespace Intersect
{
//! LineToPointDistanceTime computes the time of the shortest distance from point 'p' to segment (s1,s2).
- //! To calculate the point of intersection:
- //! P = s1 + u (s2 - s1)
- //! @param s1 segment start point
- //! @param s2 segment end point
- //! @param p point to find the closest time to.
- //! @return time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)]
- inline float LineToPointDistanceTime(const Vector3& s1, const Vector3& s21, const Vector3& p)
- {
- // so u = (p.x - s1.x)*(s2.x - s1.x) + (p.y - s1.y)*(s2.y - s1.y) + (p.z-s1.z)*(s2.z-s1.z) / |s2-s1|^2
- return s21.Dot(p - s1) / s21.Dot(s21);
- }
+ //! To calculate the point of intersection: P = s1 + u (s2 - s1)
+ //! @param s1 Segment start point.
+ //! @param s2 Segment end point.
+ //! @param p Point to find the closest time to.
+ //! @return Time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)]
+ float LineToPointDistanceTime(const Vector3& s1, const Vector3& s21, const Vector3& p);
//! LineToPointDistance computes the closest point to 'p' from a segment (s1,s2).
- //! @param s1 segment start point
- //! @param s2 segment end point
- //! @param p point to find the closest time to.
- //! @param u time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)]
- //! @return the closest point
- inline Vector3 LineToPointDistance(const Vector3& s1, const Vector3& s2, const Vector3& p, float& u)
- {
- const Vector3 s21 = s2 - s1;
- // we assume seg1 and seg2 are NOT coincident
- AZ_MATH_ASSERT(!s21.IsClose(Vector3(0.0f), 1e-4f), "OK we agreed that we will pass valid segments! (s1 != s2)");
-
- u = LineToPointDistanceTime(s1, s21, p);
-
- return s1 + u * s21;
- }
+ //! @param s1 Segment start point
+ //! @param s2 Segment end point
+ //! @param p Point to find the closest time to.
+ //! @param u Time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)]
+ //! @return The closest point
+ Vector3 LineToPointDistance(const Vector3& s1, const Vector3& s2, const Vector3& p, float& u);
//! Given segment pq and triangle abc (CCW), returns whether segment intersects
//! triangle and if so, also returns the barycentric coordinates (u,v,w)
//! of the intersection point.
- //! @param p segment start point
- //! @param q segment end point
- //! @param a triangle point 1
- //! @param b triangle point 2
- //! @param c triangle point 3
- //! @param normal at the intersection point.
- //! @param t time of intersection along the segment [0.0 (p), 1.0 (q)]
- //! @return 1 if the segment intersects the triangle otherwise 0
- int IntersectSegmentTriangleCCW(
- const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c,
- /*float &u, float &v, float &w,*/ Vector3& normal, float& t);
+ //! @param p Segment start point.
+ //! @param q Segment end point.
+ //! @param a Triangle point 1.
+ //! @param b Triangle point 2.
+ //! @param c Triangle point 3.
+ //! @param normal At the intersection point.
+ //! @param t Time of intersection along the segment [0.0 (p), 1.0 (q)].
+ //! @return true if the segments intersects the triangle otherwise false.
+ bool IntersectSegmentTriangleCCW(
+ const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c, Vector3& normal, float& t);
//! Same as \ref IntersectSegmentTriangleCCW without respecting the triangle (a,b,c) vertex order (double sided).
- int IntersectSegmentTriangle(
- const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c,
- /*float &u, float &v, float &w,*/ Vector3& normal, float& t);
+ //! @param p Segment start point.
+ //! @param q Segment end point.
+ //! @param a Triangle point 1.
+ //! @param b Triangle point 2.
+ //! @param c Triangle point 3.
+ //! @param normal At the intersection point.
+ //! @param t Time of intersection along the segment [0.0 (p), 1.0 (q)].
+ //! @return True if the segments intersects the triangle otherwise false.
+ bool IntersectSegmentTriangle(
+ const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c, Vector3& normal, float& t);
//! Ray aabb intersection result types.
- enum RayAABBIsectTypes
+ enum RayAABBIsectTypes : AZ::s32
{
- ISECT_RAY_AABB_NONE = 0, ///< no intersection
- ISECT_RAY_AABB_SA_INSIDE, ///< the ray starts inside the aabb
- ISECT_RAY_AABB_ISECT, ///< intersects along the PQ segment
+ ISECT_RAY_AABB_NONE = 0, ///< no intersection
+ ISECT_RAY_AABB_SA_INSIDE, ///< the ray starts inside the aabb
+ ISECT_RAY_AABB_ISECT, ///< intersects along the PQ segment
};
//! Intersect ray R(t) = rayStart + t*d against AABB a. When intersecting,
//! return intersection distance tmin and point q of intersection.
- //! @param rayStart ray starting point
- //! @param dir ray direction and length (dir = rayEnd - rayStart)
- //! @param dirRCP 1/dir (reciprocal direction - we cache this result very often so we don't need to compute it multiple times, otherwise just use dir.GetReciprocal())
+ //! @param rayStart Ray starting point
+ //! @param dir Ray direction and length (dir = rayEnd - rayStart)
+ //! @param dirRCP 1/dir (reciprocal direction - we cache this result very often so we don't need to compute it multiple times,
+ //! otherwise just use dir.GetReciprocal())
//! @param aabb Axis aligned bounding box to intersect against
- //! @param tStart time on ray of the first intersection [0,1] or 0 if the ray starts inside the aabb - check the return value
- //! @param tEnd time of the of the second intersection [0,1] (it can be > 1 if intersects after the rayEnd)
- //! @param startNormal normal at the start point.
+ //! @param tStart Time on ray of the first intersection [0,1] or 0 if the ray starts inside the aabb - check the return value
+ //! @param tEnd Time of the of the second intersection [0,1] (it can be > 1 if intersects after the rayEnd)
+ //! @param startNormal Normal at the start point.
//! @return \ref RayAABBIsectTypes
- int IntersectRayAABB(
- const Vector3& rayStart, const Vector3& dir, const Vector3& dirRCP, const Aabb& aabb,
- float& tStart, float& tEnd, Vector3& startNormal /*, Vector3& inter*/);
+ RayAABBIsectTypes IntersectRayAABB(
+ const Vector3& rayStart,
+ const Vector3& dir,
+ const Vector3& dirRCP,
+ const Aabb& aabb,
+ float& tStart,
+ float& tEnd,
+ Vector3& startNormal);
//! Intersect ray against AABB.
- //! @param rayStart ray starting point.
- //! @param dir ray reciprocal direction.
+ //! @param rayStart Ray starting point.
+ //! @param dir Ray reciprocal direction.
//! @param aabb Axis aligned bounding box to intersect against.
- //! @param start length on ray of the first intersection.
- //! @param end length of the of the second intersection.
- //! @return \ref RayAABBIsectTypes In this faster version than IntersectRayAABB we return only ISECT_RAY_AABB_NONE and ISECT_RAY_AABB_ISECT.
- //! You can check yourself for that case.
- int IntersectRayAABB2(
- const Vector3& rayStart, const Vector3& dirRCP, const Aabb& aabb,
- float& start, float& end);
+ //! @param start Length on ray of the first intersection.
+ //! @param end Length of the of the second intersection.
+ //! @return \ref RayAABBIsectTypes In this faster version than IntersectRayAABB we return only ISECT_RAY_AABB_NONE and
+ //! ISECT_RAY_AABB_ISECT. You can check yourself for that case.
+ RayAABBIsectTypes IntersectRayAABB2(const Vector3& rayStart, const Vector3& dirRCP, const Aabb& aabb, float& start, float& end);
//! Clip a ray to an aabb. return true if ray was clipped. The ray
//! can be inside so don't use the result if the ray intersect the box.
- inline int ClipRayWithAabb(
- const Aabb& aabb, Vector3& rayStart, Vector3& rayEnd, float& tClipStart, float& tClipEnd)
- {
- Vector3 startNormal;
- float tStart, tEnd;
- Vector3 dirLen = rayEnd - rayStart;
- if (IntersectRayAABB(rayStart, dirLen, dirLen.GetReciprocal(), aabb, tStart, tEnd, startNormal) != ISECT_RAY_AABB_NONE)
- {
- // clip the ray with the box
- if (tStart > 0.0f)
- {
- rayStart = rayStart + tStart * dirLen;
- tClipStart = tStart;
- }
- if (tEnd < 1.0f)
- {
- rayEnd = rayStart + tEnd * dirLen;
- tClipEnd = tEnd;
- }
-
- return 1;
- }
-
- return 0;
- }
+ //! @param aabb Bounds to test against.
+ //! @param rayStart The start of the ray.
+ //! @param rayEnd The end of the ray.
+ //! @param[out] tClipStart The proportion where the ray enters the \ref Aabb.
+ //! @param[out] tClipEnd The proportion where the ray exits the \ref Aabb.
+ //! @return True if the ray was clipped, otherwise false.
+ bool ClipRayWithAabb(const Aabb& aabb, Vector3& rayStart, Vector3& rayEnd, float& tClipStart, float& tClipEnd);
//! Test segment and aabb where the segment is defined by midpoint
//! midPoint = (p1-p0) * 0.5f and half vector halfVector = p1 - midPoint.
//! the aabb is at the origin and defined by half extents only.
- //! @return 1 if the intersect, otherwise 0.
- int TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& halfVector, const Vector3& aabbExtends);
+ //! @param midPoint Midpoint of a line segment.
+ //! @param halfVector Half vector of an aabb.
+ //! @param aabbExtends The extends of a bounded box.
+ //! @return True if the segment and AABB intersect, otherwise false
+ bool TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& halfVector, const Vector3& aabbExtends);
- //! Test if segment specified by points p0 and p1 intersects AABB. \ref TestSegmentAABBOrigin
- //! @return 1 if the segment and AABB intersect, otherwise 0.
- inline int TestSegmentAABB(const Vector3& p0, const Vector3& p1, const Aabb& aabb)
- {
- Vector3 e = aabb.GetExtents();
- Vector3 d = p1 - p0;
- Vector3 m = p0 + p1 - aabb.GetMin() - aabb.GetMax();
-
- return TestSegmentAABBOrigin(m, d, e);
- }
+ //! Test if segment specified by points p0 and p1 intersects AABB. \ref TestSegmentAABBOrigin.
+ //! @param p0 Segment start point.
+ //! @param p1 Segment end point.
+ //! @param aabb Bounded box to test against.
+ //! @return True if the segment and AABB intersect, otherwise false.
+ bool TestSegmentAABB(const Vector3& p0, const Vector3& p1, const Aabb& aabb);
//! Ray sphere intersection result types.
- enum SphereIsectTypes
+ enum SphereIsectTypes : AZ::s32
{
- ISECT_RAY_SPHERE_SA_INSIDE = -1, // the ray starts inside the cylinder
- ISECT_RAY_SPHERE_NONE, // no intersection
- ISECT_RAY_SPHERE_ISECT, // along the PQ segment
+ ISECT_RAY_SPHERE_SA_INSIDE = -1, //!< The ray starts inside the cylinder
+ ISECT_RAY_SPHERE_NONE, //!< No intersection
+ ISECT_RAY_SPHERE_ISECT, //!< Along the PQ segment
};
//! IntersectRaySphereOrigin
//! return time t>=0 but not limited, so if you check a segment make sure
- //! t <= segmentLen
- //! @param rayStart ray start point
+ //! t <= segmentLen.
+ //! @param rayStart ray start point.
//! @param rayDirNormalized ray direction normalized.
- //! @param shereRadius sphere radius
+ //! @param shereRadius Radius of sphere at origin.
//! @param time of closest intersection [0,+INF] in relation to the normalized direction.
- //! @return \ref SphereIsectTypes
- AZ_INLINE int IntersectRaySphereOrigin(
- const Vector3& rayStart, const Vector3& rayDirNormalized,
- const float sphereRadius, float& t)
- {
- Vector3 m = rayStart;
- float b = m.Dot(rayDirNormalized);
- float c = m.Dot(m) - sphereRadius * sphereRadius;
-
- // Exit if r's origin outside s (c > 0)and r pointing away from s (b > 0)
- if (c > 0.0f && b > 0.0f)
- {
- return ISECT_RAY_SPHERE_NONE;
- }
- float discr = b * b - c;
- // A negative discriminant corresponds to ray missing sphere
- if (discr < 0.0f)
- {
- return ISECT_RAY_SPHERE_NONE;
- }
-
- // Ray now found to intersect sphere, compute smallest t value of intersection
- t = -b - Sqrt(discr);
-
- // If t is negative, ray started inside sphere so clamp t to zero
- if (t < 0.0f)
- {
- // t = 0.0f;
- return ISECT_RAY_SPHERE_SA_INSIDE; // no hit if inside
- }
- //q = p + t * d;
- return ISECT_RAY_SPHERE_ISECT;
- }
+ //! @return \ref SphereIsectTypes.
+ SphereIsectTypes IntersectRaySphereOrigin(
+ const Vector3& rayStart, const Vector3& rayDirNormalized, const float sphereRadius, float& t);
//! Intersect ray (rayStart,rayDirNormalized) and sphere (sphereCenter,sphereRadius) \ref IntersectRaySphereOrigin
- inline int IntersectRaySphere(
- const Vector3& rayStart, const Vector3& rayDirNormalized, const Vector3& sphereCenter, const float sphereRadius, float& t)
- {
- return IntersectRaySphereOrigin(rayStart - sphereCenter, rayDirNormalized, sphereRadius, t);
- }
+ //! @param rayStart The start of the ray.
+ //! @param rayDirNormalized The direction of the ray normalized.
+ //! @param sphereCenter The center of the sphere.
+ //! @param sphereRadius Radius of the sphere.
+ //! @param[out] t Coefficient in the ray's explicit equation from which an
+ //! intersecting point is calculated as "rayOrigin + t1 * rayDir".
+ //! @return SphereIsectTypes
+ SphereIsectTypes IntersectRaySphere(
+ const Vector3& rayStart, const Vector3& rayDirNormalized, const Vector3& sphereCenter, const float sphereRadius, float& t);
- //! @param rayOrigin The origin of the ray to test.
- //! @param rayDir The direction of the ray to test. It has to be unit length.
- //! @param diskCenter Center point of the disk
- //! @param diskRadius Radius of the disk
- //! @param diskNormal A normal perpendicular to the disk
- //! @param[out] t If returning 1 (indicating a hit), this contains distance from rayOrigin along the normalized rayDir that the hit occured at.
- //! @return The number of intersecting points.
- int IntersectRayDisk(
- const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& diskCenter, const float diskRadius, const AZ::Vector3& diskNormal, float& t);
+ //! Intersect ray (rayStarty, rayDirNormalized) and disk (center, radius, normal)
+ //! @param rayOrigin The origin of the ray to test.
+ //! @param rayDir The direction of the ray to test. It has to be unit length.
+ //! @param diskCenter Center point of the disk.
+ //! @param diskRadius Radius of the disk.
+ //! @param diskNormal A normal perpendicular to the disk.
+ //! @param[out] t If returning 1 (indicating a hit), this contains distance from rayOrigin along the normalized rayDir
+ //! that the hit occured at.
+ //! @return False if not interesecting and true if intersecting
+ bool IntersectRayDisk(
+ const Vector3& rayOrigin,
+ const Vector3& rayDir,
+ const Vector3& diskCenter,
+ const float diskRadius,
+ const AZ::Vector3& diskNormal,
+ float& t);
//! If there is only one intersecting point, the coefficient is stored in \ref t1.
- //! @param rayOrigin The origin of the ray to test.
- //! @param rayDir The direction of the ray to test. It has to be unit length.
- //! @param cylinderEnd1 The center of the circle on one end of the cylinder.
- //! @param cylinderDir The direction pointing from \ref cylinderEnd1 to the other end of the cylinder. It has to be unit length.
- //! @param cylinderHeight The distance between two centers of the circles on two ends of the cylinder respectively.
- //! @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t1 * rayDir".
- //! @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t2 * rayDir".
- //! @return The number of intersecting points.
+ //! @param rayOrigin The origin of the ray to test.
+ //! @param rayDir The direction of the ray to test. It has to be unit length.
+ //! @param cylinderEnd1 The center of the circle on one end of the cylinder.
+ //! @param cylinderDir The direction pointing from \ref cylinderEnd1 to the other end of the cylinder. It has to be unit length.
+ //! @param cylinderHeight The distance between two centers of the circles on two ends of the cylinder respectively.
+ //! @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t1 * rayDir".
+ //! @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t2 * rayDir".
+ //! @return The number of intersecting points.
int IntersectRayCappedCylinder(
- const Vector3& rayOrigin, const Vector3& rayDir,
- const Vector3& cylinderEnd1, const Vector3& cylinderDir, float cylinderHeight, float cylinderRadius,
- float& t1, float& t2);
+ const Vector3& rayOrigin,
+ const Vector3& rayDir,
+ const Vector3& cylinderEnd1,
+ const Vector3& cylinderDir,
+ float cylinderHeight,
+ float cylinderRadius,
+ float& t1,
+ float& t2);
//! If there is only one intersecting point, the coefficient is stored in \ref t1.
- //! @param rayOrigin The origin of the ray to test.
- //! @param rayDir The direction of the ray to test. It has to be unit length.
- //! @param coneApex The apex of the cone.
- //! @param coneDir The unit-length direction from the apex to the base.
- //! @param coneHeight The height of the cone, from the apex to the base.
- //! @param coneBaseRadius The radius of the cone base circle.
- //! @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t1 * rayDir".
- //! @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t2 * rayDir".
- //! @return The number of intersecting points.
+ //! @param rayOrigin The origin of the ray to test.
+ //! @param rayDir The direction of the ray to test. It has to be unit length.
+ //! @param coneApex The apex of the cone.
+ //! @param coneDir The unit-length direction from the apex to the base.
+ //! @param coneHeight The height of the cone, from the apex to the base.
+ //! @param coneBaseRadius The radius of the cone base circle.
+ //! @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t1 * rayDir".
+ //! @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t2 * rayDir".
+ //! @return The number of intersecting points.
int IntersectRayCone(
- const Vector3& rayOrigin, const Vector3& rayDir,
- const Vector3& coneApex, const Vector3& coneDir, float coneHeight, float coneBaseRadius,
- float& t1, float& t2);
+ const Vector3& rayOrigin,
+ const Vector3& rayDir,
+ const Vector3& coneApex,
+ const Vector3& coneDir,
+ float coneHeight,
+ float coneBaseRadius,
+ float& t1,
+ float& t2);
//! Test intersection between a ray and a plane in 3D.
- //! @param rayOrigin The origin of the ray to test intersection with.
- //! @param rayDir The direction of the ray to test intersection with.
- //! @param planePos A point on the plane to test intersection with.
- //! @param planeNormal The normal of the plane to test intersection with.
- //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection".
- //! @return The number of intersection point.
+ //! @param rayOrigin The origin of the ray to test intersection with.
+ //! @param rayDir The direction of the ray to test intersection with.
+ //! @param planePos A point on the plane to test intersection with.
+ //! @param planeNormal The normal of the plane to test intersection with.
+ //! @param[out] t The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection".
+ //! @return The number of intersection point.
int IntersectRayPlane(
- const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& planePos,
- const Vector3& planeNormal, float& t);
+ const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& planePos, const Vector3& planeNormal, float& t);
//! Test intersection between a ray and a two-sided quadrilateral defined by four points in 3D.
- //! The four points that define the quadrilateral could be passed in with either counter clock-wise
+ //! The four points that define the quadrilateral could be passed in with either counter clock-wise
//! winding or clock-wise winding.
- //! @param rayOrigin The origin of the ray to test intersection with.
- //! @param rayDir The direction of the ray to test intersection with.
- //! @param vertexA One of the four points that define the quadrilateral.
- //! @param vertexB One of the four points that define the quadrilateral.
- //! @param vertexC One of the four points that define the quadrilateral.
- //! @param vertexD One of the four points that define the quadrilateral.
- //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection".
- //! @return The number of intersection point.
+ //! @param rayOrigin The origin of the ray to test intersection with.
+ //! @param rayDir The direction of the ray to test intersection with.
+ //! @param vertexA One of the four points that define the quadrilateral.
+ //! @param vertexB One of the four points that define the quadrilateral.
+ //! @param vertexC One of the four points that define the quadrilateral.
+ //! @param vertexD One of the four points that define the quadrilateral.
+ //! @param[out] t The coefficient in the ray's explicit equation from which the
+ //! intersecting point is calculated as "rayOrigin + t * rayDirection".
+ //! @return The number of intersection point.
int IntersectRayQuad(
- const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& vertexA,
- const Vector3& vertexB, const Vector3& vertexC, const Vector3& vertexD, float& t);
+ const Vector3& rayOrigin,
+ const Vector3& rayDir,
+ const Vector3& vertexA,
+ const Vector3& vertexB,
+ const Vector3& vertexC,
+ const Vector3& vertexD,
+ float& t);
- //! Test intersection between a ray and an oriented box in 3D.
- //! @param rayOrigin The origin of the ray to test intersection with.
- //! @param rayDir The direction of the ray to test intersection with.
- //! @param boxCenter The position of the center of the box.
- //! @param boxAxis1 An axis along one dimension of the oriented box.
- //! @param boxAxis2 An axis along one dimension of the oriented box.
- //! @param boxAxis3 An axis along one dimension of the oriented box.
- //! @param boxHalfExtent1 The half extent of the box on the dimension of \ref boxAxis1.
- //! @param boxHalfExtent2 The half extent of the box on the dimension of \ref boxAxis2.
- //! @param boxHalfExtent3 The half extent of the box on the dimension of \ref boxAxis3.
- //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection".
- //! @return 1 if there is an intersection, 0 otherwise.
- int IntersectRayBox(
- const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& boxCenter, const Vector3& boxAxis1,
- const Vector3& boxAxis2, const Vector3& boxAxis3, float boxHalfExtent1, float boxHalfExtent2, float boxHalfExtent3,
+ //! Test intersection between a ray and an oriented box in 3D.
+ //! @param rayOrigin The origin of the ray to test intersection with.
+ //! @param rayDir The direction of the ray to test intersection with.
+ //! @param boxCenter The position of the center of the box.
+ //! @param boxAxis1 An axis along one dimension of the oriented box.
+ //! @param boxAxis2 An axis along one dimension of the oriented box.
+ //! @param boxAxis3 An axis along one dimension of the oriented box.
+ //! @param boxHalfExtent1 The half extent of the box on the dimension of \ref boxAxis1.
+ //! @param boxHalfExtent2 The half extent of the box on the dimension of \ref boxAxis2.
+ //! @param boxHalfExtent3 The half extent of the box on the dimension of \ref boxAxis3.
+ //! @param[out] t The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection".
+ //! @return true if there is an intersection, false otherwise.
+ bool IntersectRayBox(
+ const Vector3& rayOrigin,
+ const Vector3& rayDir,
+ const Vector3& boxCenter,
+ const Vector3& boxAxis1,
+ const Vector3& boxAxis2,
+ const Vector3& boxAxis3,
+ float boxHalfExtent1,
+ float boxHalfExtent2,
+ float boxHalfExtent3,
float& t);
//! Test intersection between a ray and an OBB.
//! @param rayOrigin The origin of the ray to test intersection with.
//! @param rayDir The direction of the ray to test intersection with.
//! @param obb The OBB to test for intersection with the ray.
- //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection".
- //! @return 1 if there is an intersection, 0 otherwise.
- int IntersectRayObb(const Vector3& rayOrigin, const Vector3& rayDir, const Obb& obb, float& t);
+ //! @param[out] t The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection".
+ //! @return True if there is an intersection, false otherwise.
+ bool IntersectRayObb(const Vector3& rayOrigin, const Vector3& rayDir, const Obb& obb, float& t);
//! Ray cylinder intersection types.
- enum CylinderIsectTypes
+ enum CylinderIsectTypes : AZ::s32
{
- RR_ISECT_RAY_CYL_SA_INSIDE = -1, // the ray starts inside the cylinder
- RR_ISECT_RAY_CYL_NONE, // no intersection
- RR_ISECT_RAY_CYL_PQ, // along the PQ segment
- RR_ISECT_RAY_CYL_P_SIDE, // on the P side
- RR_ISECT_RAY_CYL_Q_SIDE, // on the Q side
+ RR_ISECT_RAY_CYL_SA_INSIDE = -1, //!< the ray starts inside the cylinder
+ RR_ISECT_RAY_CYL_NONE, //!< no intersection
+ RR_ISECT_RAY_CYL_PQ, //!< along the PQ segment
+ RR_ISECT_RAY_CYL_P_SIDE, //!< on the P side
+ RR_ISECT_RAY_CYL_Q_SIDE, //!< on the Q side
};
+ //! Reference: Real-Time Collision Detection - 5.3.7 Intersecting Ray or Segment Against Cylinder
//! Intersect segment S(t)=sa+t(dir), 0<=t<=1 against cylinder specified by p, q and r.
- int IntersectSegmentCylinder(
- const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q,
- const float r, float& t);
+ //! @param sa The initial point.
+ //! @param dir Magnitude and direction for sa.
+ //! @param p Center point of side 1 cylinder.
+ //! @param q Center point of side 2 cylinder.
+ //! @param r Radius of cylinder.
+ //! @param[out] t Proporition along line segment.
+ //! @return CylinderIsectTypes
+ CylinderIsectTypes IntersectSegmentCylinder(
+ const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t);
//! Capsule ray intersect types.
enum CapsuleIsectTypes
{
- ISECT_RAY_CAPSULE_SA_INSIDE = -1, // the ray starts inside the cylinder
- ISECT_RAY_CAPSULE_NONE, // no intersection
- ISECT_RAY_CAPSULE_PQ, // along the PQ segment
- ISECT_RAY_CAPSULE_P_SIDE, // on the P side
- ISECT_RAY_CAPSULE_Q_SIDE, // on the Q side
+ ISECT_RAY_CAPSULE_SA_INSIDE = -1, //!< The ray starts inside the cylinder
+ ISECT_RAY_CAPSULE_NONE, //!< No intersection
+ ISECT_RAY_CAPSULE_PQ, //!< Along the PQ segment
+ ISECT_RAY_CAPSULE_P_SIDE, //!< On the P side
+ ISECT_RAY_CAPSULE_Q_SIDE, //!< On the Q side
};
//! This is a quick implementation of segment capsule based on segment cylinder \ref IntersectSegmentCylinder
//! segment sphere intersection. We can optimize it a lot once we fix the ray
//! cylinder intersection.
- int IntersectSegmentCapsule(
- const Vector3& sa, const Vector3& dir, const Vector3& p,
- const Vector3& q, const float r, float& t);
+ //! @param sa The beginning of the line segment.
+ //! @param dir The direction and length of the segment.
+ //! @param p Center point of side 1 capsule.
+ //! @param q Center point of side 1 capsule.
+ //! @param r The radius of the capsule.
+ //! @param[out] t Proporition along line segment.
+ //! @return CapsuleIsectTypes
+ CapsuleIsectTypes IntersectSegmentCapsule(
+ const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t);
//! Intersect segment S(t)=A+t(B-A), 0<=t<=1 against convex polyhedron specified
//! by the n halfspaces defined by the planes p[]. On exit tfirst and tlast
//! define the intersection, if any.
- int IntersectSegmentPolyhedron(
- const Vector3& sa, const Vector3& sBA, const Plane p[], int numPlanes,
- float& tfirst, float& tlast, int& iFirstPlane, int& iLastPlane);
+ //! @param sa The beggining of the line segment.
+ //! @param dir The direction and length of the segment.
+ //! @param p Planes that compose a convex ponvex polyhedron.
+ //! @param numPlanes number of planes.
+ //! @param[out] tfirst Proportion along the line segment where the line enters.
+ //! @param[out] tlast Proportion along the line segment where the line exits.
+ //! @param[out] iFirstPlane The plane where the line enters.
+ //! @param[out] iLastPlane The plane where the line exits.
+ //! @return True if intersects else false.
+ bool IntersectSegmentPolyhedron(
+ const Vector3& sa,
+ const Vector3& dir,
+ const Plane p[],
+ int numPlanes,
+ float& tfirst,
+ float& tlast,
+ int& iFirstPlane,
+ int& iLastPlane);
//! Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between
- //! two segments segment1Start<->segment1End and segment2Start<->segment2End. Also calculate the values of segment1Proportion and segment2Proportion where
- //! closestPointSegment1 = segment1Start + (segment1Proportion * (segment1End - segment1Start))
+ //! two segments segment1Start<->segment1End and segment2Start<->segment2End. Also calculate the values of segment1Proportion and
+ //! segment2Proportion where closestPointSegment1 = segment1Start + (segment1Proportion * (segment1End - segment1Start))
//! closestPointSegment2 = segment2Start + (segment2Proportion * (segment2End - segment2Start))
//! If segments are parallel returns a solution.
+ //! @param segment1Start Start of segment 1.
+ //! @param segment1End End of segment 1.
+ //! @param segment2Start Start of segment 2.
+ //! @param segment2End End of segment 2.
+ //! @param[out] segment1Proportion The proporition along segment 1 [0..1]
+ //! @param[out] segment2Proportion The proporition along segment 2 [0..1]
+ //! @param[out] closestPointSegment1 Closest point on segment 1.
+ //! @param[out] closestPointSegment2 Closest point on segment 2.
+ //! @param epsilon The minimum square distance where a line segment can be treated as a single point.
void ClosestSegmentSegment(
- const Vector3& segment1Start, const Vector3& segment1End,
- const Vector3& segment2Start, const Vector3& segment2End,
- float& segment1Proportion, float& segment2Proportion,
- Vector3& closestPointSegment1, Vector3& closestPointSegment2,
+ const Vector3& segment1Start,
+ const Vector3& segment1End,
+ const Vector3& segment2Start,
+ const Vector3& segment2End,
+ float& segment1Proportion,
+ float& segment2Proportion,
+ Vector3& closestPointSegment1,
+ Vector3& closestPointSegment2,
float epsilon = 1e-4f);
//! Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between
//! two segments segment1Start<->segment1End and segment2Start<->segment2End.
//! If segments are parallel returns a solution.
+ //! @param segment1Start Start of segment 1.
+ //! @param segment1End End of segment 1.
+ //! @param segment2Start Start of segment 2.
+ //! @param segment2End End of segment 2.
+ //! @param[out] closestPointSegment1 Closest point on segment 1.
+ //! @param[out] closestPointSegment2 Closest point on segment 2.
+ //! @param epsilon The minimum square distance where a line segment can be treated as a single point.
void ClosestSegmentSegment(
- const Vector3& segment1Start, const Vector3& segment1End,
- const Vector3& segment2Start, const Vector3& segment2End,
- Vector3& closestPointSegment1, Vector3& closestPointSegment2,
+ const Vector3& segment1Start,
+ const Vector3& segment1End,
+ const Vector3& segment2Start,
+ const Vector3& segment2End,
+ Vector3& closestPointSegment1,
+ Vector3& closestPointSegment2,
float epsilon = 1e-4f);
//! Calculate the point (closestPointOnSegment) that is the closest point on
//! segment segmentStart/segmentEnd to point. Also calculate the value of proportion where
//! closestPointOnSegment = segmentStart + (proportion * (segmentEnd - segmentStart))
+ //! @param point The point to test
+ //! @param segmentStart The start of the segment
+ //! @param segmentEnd The end of the segment
+ //! @param[out] proportion The proportion of the segment L(t) = (end - start) * t
+ //! @param[out] closestPointOnSegment The point along the line segment
void ClosestPointSegment(
- const Vector3& point, const Vector3& segmentStart, const Vector3& segmentEnd,
- float& proportion, Vector3& closestPointOnSegment);
- }
-}
+ const Vector3& point,
+ const Vector3& segmentStart,
+ const Vector3& segmentEnd,
+ float& proportion,
+ Vector3& closestPointOnSegment);
+ } // namespace Intersect
+} // namespace AZ
-#endif // AZCORE_MATH_SEGMENT_INTERSECTION_H
-#pragma once
+#include
diff --git a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.inl b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.inl
new file mode 100644
index 0000000000..b570b6a182
--- /dev/null
+++ b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.inl
@@ -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
+ *
+ */
+
+namespace AZ
+{
+ namespace Intersect
+ {
+ AZ_MATH_INLINE bool ClipRayWithAabb(const Aabb& aabb, Vector3& rayStart, Vector3& rayEnd, float& tClipStart, float& tClipEnd)
+ {
+ Vector3 startNormal;
+ float tStart, tEnd;
+ Vector3 dirLen = rayEnd - rayStart;
+ if (IntersectRayAABB(rayStart, dirLen, dirLen.GetReciprocal(), aabb, tStart, tEnd, startNormal) != ISECT_RAY_AABB_NONE)
+ {
+ // clip the ray with the box
+ if (tStart > 0.0f)
+ {
+ rayStart = rayStart + tStart * dirLen;
+ tClipStart = tStart;
+ }
+ if (tEnd < 1.0f)
+ {
+ rayEnd = rayStart + tEnd * dirLen;
+ tClipEnd = tEnd;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ AZ_MATH_INLINE SphereIsectTypes
+ IntersectRaySphereOrigin(const Vector3& rayStart, const Vector3& rayDirNormalized, const float sphereRadius, float& t)
+ {
+ Vector3 m = rayStart;
+ float b = m.Dot(rayDirNormalized);
+ float c = m.Dot(m) - sphereRadius * sphereRadius;
+
+ // Exit if r's origin outside s (c > 0)and r pointing away from s (b > 0)
+ if (c > 0.0f && b > 0.0f)
+ {
+ return ISECT_RAY_SPHERE_NONE;
+ }
+ float discr = b * b - c;
+ // A negative discriminant corresponds to ray missing sphere
+ if (discr < 0.0f)
+ {
+ return ISECT_RAY_SPHERE_NONE;
+ }
+
+ // Ray now found to intersect sphere, compute smallest t value of intersection
+ t = -b - Sqrt(discr);
+
+ // If t is negative, ray started inside sphere so clamp t to zero
+ if (t < 0.0f)
+ {
+ // t = 0.0f;
+ return ISECT_RAY_SPHERE_SA_INSIDE; // no hit if inside
+ }
+ // q = p + t * d;
+ return ISECT_RAY_SPHERE_ISECT;
+ }
+
+ AZ_MATH_INLINE SphereIsectTypes IntersectRaySphere(const Vector3& rayStart, const Vector3& rayDirNormalized, const Vector3& sphereCenter, const float sphereRadius, float& t)
+ {
+ return IntersectRaySphereOrigin(rayStart - sphereCenter, rayDirNormalized, sphereRadius, t);
+ }
+
+ AZ_MATH_INLINE Vector3 LineToPointDistance(const Vector3& s1, const Vector3& s2, const Vector3& p, float& u)
+ {
+ const Vector3 s21 = s2 - s1;
+ // we assume seg1 and seg2 are NOT coincident
+ AZ_MATH_ASSERT(!s21.IsClose(Vector3(0.0f), 1e-4f), "OK we agreed that we will pass valid segments! (s1 != s2)");
+
+ u = LineToPointDistanceTime(s1, s21, p);
+
+ return s1 + u * s21;
+ }
+
+ AZ_MATH_INLINE float LineToPointDistanceTime(const Vector3& s1, const Vector3& s21, const Vector3& p)
+ {
+ // so u = (p.x - s1.x)*(s2.x - s1.x) + (p.y - s1.y)*(s2.y - s1.y) + (p.z-s1.z)*(s2.z-s1.z) / |s2-s1|^2
+ return s21.Dot(p - s1) / s21.Dot(s21);
+ }
+
+ AZ_MATH_INLINE bool TestSegmentAABB(const Vector3& p0, const Vector3& p1, const Aabb& aabb)
+ {
+ Vector3 e = aabb.GetExtents();
+ Vector3 d = p1 - p0;
+ Vector3 m = p0 + p1 - aabb.GetMin() - aabb.GetMax();
+
+ return TestSegmentAABBOrigin(m, d, e);
+ }
+ } // namespace Intersect
+} // namespace AZ
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/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake
index 6675958247..4d95ddf098 100644
--- a/Code/Framework/AzCore/AzCore/azcore_files.cmake
+++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake
@@ -282,6 +282,7 @@ set(FILES
Math/Internal/VertexContainer.inl
Math/InterpolationSample.h
Math/IntersectPoint.h
+ Math/IntersectSegment.inl
Math/IntersectSegment.cpp
Math/IntersectSegment.h
Math/MathIntrinsics.h
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/AzFramework/AzFramework/Gem/GemInfo.h b/Code/Framework/AzFramework/AzFramework/Gem/GemInfo.h
index 1f300af770..3435d810fd 100644
--- a/Code/Framework/AzFramework/AzFramework/Gem/GemInfo.h
+++ b/Code/Framework/AzFramework/AzFramework/Gem/GemInfo.h
@@ -29,6 +29,10 @@ namespace AzFramework
AZStd::vector m_absoluteSourcePaths; //!< Where the gem's source path folder are located(as an absolute path)
static constexpr const char* GetGemAssetFolder() { return "Assets"; }
+ static constexpr const char* GetGemRegistryFolder()
+ {
+ return "Registry";
+ }
};
//! Returns a list of GemInfo of all the gems that are active for the for the specified game project.
diff --git a/Code/Framework/AzFramework/AzFramework/Input/System/InputSystemComponent.cpp b/Code/Framework/AzFramework/AzFramework/Input/System/InputSystemComponent.cpp
index 33690f2246..14fb7ea5eb 100644
--- a/Code/Framework/AzFramework/AzFramework/Input/System/InputSystemComponent.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Input/System/InputSystemComponent.cpp
@@ -20,6 +20,7 @@
#include
#include
#include
+#include
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace AzFramework
@@ -190,6 +191,25 @@ namespace AzFramework
////////////////////////////////////////////////////////////////////////////////////////////////
void InputSystemComponent::Activate()
{
+ const auto* settingsRegistry = AZ::SettingsRegistry::Get();
+ if (settingsRegistry)
+ {
+ AZ::u64 value = 0;
+ if (settingsRegistry->Get(value, "/O3DE/InputSystem/MouseMovementSampleRateHertz"))
+ {
+ m_mouseMovementSampleRateHertz = aznumeric_caster(value);
+ }
+ if (settingsRegistry->Get(value, "/O3DE/InputSystem/GamepadsEnabled"))
+ {
+ m_gamepadsEnabled = aznumeric_caster(value);
+ }
+ settingsRegistry->Get(m_keyboardEnabled, "/O3DE/InputSystem/KeyboardEnabled");
+ settingsRegistry->Get(m_motionEnabled, "/O3DE/InputSystem/MotionEnabled");
+ settingsRegistry->Get(m_mouseEnabled, "/O3DE/InputSystem/MouseEnabled");
+ settingsRegistry->Get(m_touchEnabled, "/O3DE/InputSystem/TouchEnabled");
+ settingsRegistry->Get(m_virtualKeyboardEnabled, "/O3DE/InputSystem/VirtualKeyboardEnabled");
+ }
+
// Create all enabled input devices
CreateEnabledInputDevices();
diff --git a/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.cpp b/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.cpp
index 0c879a930f..0856ddeed6 100644
--- a/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.cpp
@@ -22,6 +22,7 @@ namespace AzFramework
->Field("terminationTime", &SessionConfig::m_terminationTime)
->Field("creatorId", &SessionConfig::m_creatorId)
->Field("sessionProperties", &SessionConfig::m_sessionProperties)
+ ->Field("matchmakingData", &SessionConfig::m_matchmakingData)
->Field("sessionId", &SessionConfig::m_sessionId)
->Field("sessionName", &SessionConfig::m_sessionName)
->Field("dnsName", &SessionConfig::m_dnsName)
@@ -46,6 +47,8 @@ namespace AzFramework
"CreatorId", "A unique identifier for a player or entity creating the session.")
->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_sessionProperties,
"SessionProperties", "A collection of custom properties for a session.")
+ ->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_matchmakingData,
+ "MatchmakingData", "The matchmaking process information that was used to create the session.")
->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_sessionId,
"SessionId", "A unique identifier for the session.")
->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_sessionName,
diff --git a/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.h b/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.h
index cfd6aa7c8b..45e40c2f29 100644
--- a/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.h
+++ b/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.h
@@ -35,6 +35,9 @@ namespace AzFramework
// A collection of custom properties for a session.
AZStd::unordered_map m_sessionProperties;
+
+ // The matchmaking process information that was used to create the session.
+ AZStd::string m_matchmakingData;
// A unique identifier for the session.
AZStd::string m_sessionId;
diff --git a/Code/Framework/AzFramework/AzFramework/Session/SessionNotifications.h b/Code/Framework/AzFramework/AzFramework/Session/SessionNotifications.h
index 7788c2d030..902500fe9a 100644
--- a/Code/Framework/AzFramework/AzFramework/Session/SessionNotifications.h
+++ b/Code/Framework/AzFramework/AzFramework/Session/SessionNotifications.h
@@ -41,6 +41,11 @@ namespace AzFramework
// OnDestroySessionBegin is fired at the beginning of session termination
// @return The result of all OnDestroySessionBegin notifications
virtual bool OnDestroySessionBegin() = 0;
+
+ // OnUpdateSessionBegin is fired at the beginning of session update
+ // @param sessionConfig The properties to describe a session
+ // @param updateReason The reason for session update
+ virtual void OnUpdateSessionBegin(const SessionConfig& sessionConfig, const AZStd::string& updateReason) = 0;
};
using SessionNotificationBus = AZ::EBus;
} // namespace AzFramework
diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/RootSpawnableInterface.h b/Code/Framework/AzFramework/AzFramework/Spawnable/RootSpawnableInterface.h
index bb1f137ba2..72a3031e3e 100644
--- a/Code/Framework/AzFramework/AzFramework/Spawnable/RootSpawnableInterface.h
+++ b/Code/Framework/AzFramework/AzFramework/Spawnable/RootSpawnableInterface.h
@@ -61,6 +61,10 @@ namespace AzFramework
//! be deleted and the spawnable asset to be released. This call is automatically done when
//! AssignRootSpawnable is called while a root spawnable is assigned.
virtual void ReleaseRootSpawnable() = 0;
+ //! Force processing all SpawnableEntitiesManager requests immediately
+ //! This is useful when loading a different level while SpawnableEntitiesManager still has
+ //! pending requests
+ virtual void ProcessSpawnableQueue() = 0;
};
using RootSpawnableInterface = AZ::Interface;
diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.cpp
index f6130c9e31..957786c6df 100644
--- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.cpp
@@ -45,8 +45,7 @@ namespace AzFramework
void SpawnableSystemComponent::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/)
{
- m_entitiesManager.ProcessQueue(
- SpawnableEntitiesManager::CommandQueuePriority::High | SpawnableEntitiesManager::CommandQueuePriority::Regular);
+ ProcessSpawnableQueue();
RootSpawnableNotificationBus::ExecuteQueuedEvents();
}
@@ -121,6 +120,12 @@ namespace AzFramework
m_rootSpawnableId = AZ::Data::AssetId();
}
+ void SpawnableSystemComponent::ProcessSpawnableQueue()
+ {
+ m_entitiesManager.ProcessQueue(
+ SpawnableEntitiesManager::CommandQueuePriority::High | SpawnableEntitiesManager::CommandQueuePriority::Regular);
+ }
+
void SpawnableSystemComponent::OnRootSpawnableAssigned([[maybe_unused]] AZ::Data::Asset rootSpawnable,
[[maybe_unused]] uint32_t generation)
{
@@ -161,6 +166,8 @@ namespace AzFramework
void SpawnableSystemComponent::Deactivate()
{
+ ProcessSpawnableQueue();
+
m_registryChangeHandler.Disconnect();
AZ::TickBus::Handler::BusDisconnect();
diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.h
index 5b5fb1b7ee..74e255d624 100644
--- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.h
+++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableSystemComponent.h
@@ -75,6 +75,7 @@ namespace AzFramework
uint64_t AssignRootSpawnable(AZ::Data::Asset rootSpawnable) override;
void ReleaseRootSpawnable() override;
+ void ProcessSpawnableQueue() override;
//
// RootSpawnbleNotificationBus
diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.cpp b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.cpp
index 6ab97fd616..43f7e7140f 100644
--- a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.cpp
+++ b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.cpp
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
#include
diff --git a/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbInputDeviceKeyboardTests.cpp b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbInputDeviceKeyboardTests.cpp
index 2b1f21ede7..76d00eda50 100644
--- a/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbInputDeviceKeyboardTests.cpp
+++ b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbInputDeviceKeyboardTests.cpp
@@ -12,7 +12,6 @@
#include
-#include
#include
#include
#include
@@ -20,6 +19,7 @@
#include "Matchers.h"
#include "Actions.h"
#include "XcbBaseTestFixture.h"
+#include "XcbTestApplication.h"
template
xcb_generic_event_t MakeEvent(T event)
@@ -33,6 +33,7 @@ namespace AzFramework
class XcbInputDeviceKeyboardTests
: public XcbBaseTestFixture
{
+ public:
void SetUp() override
{
using testing::Return;
@@ -123,6 +124,15 @@ namespace AzFramework
static constexpr xcb_keycode_t s_keycodeForAKey{38};
static constexpr xcb_keycode_t s_keycodeForShiftLKey{50};
+
+ XcbTestApplication m_application{
+ /*enabledGamepadsCount=*/0,
+ /*keyboardEnabled=*/true,
+ /*motionEnabled=*/false,
+ /*mouseEnabled=*/false,
+ /*touchEnabled=*/false,
+ /*virtualKeyboardEnabled=*/false
+ };
};
class InputTextNotificationListener
@@ -195,27 +205,23 @@ namespace AzFramework
EXPECT_CALL(m_interface, xkb_state_key_get_one_sym(&m_xkbState, s_keycodeForAKey))
.Times(2);
- Application application;
- application.Start({}, {});
- AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
+ m_application.Start();
const InputChannel* inputChannel = InputChannelRequests::FindInputChannel(InputDeviceKeyboard::Key::AlphanumericA);
ASSERT_TRUE(inputChannel);
EXPECT_THAT(inputChannel->GetState(), Eq(InputChannel::State::Idle));
- application.PumpSystemEventLoopUntilEmpty();
- application.TickSystem();
- application.Tick();
+ m_application.PumpSystemEventLoopUntilEmpty();
+ m_application.TickSystem();
+ m_application.Tick();
EXPECT_THAT(inputChannel->GetState(), Eq(InputChannel::State::Began));
- application.PumpSystemEventLoopUntilEmpty();
- application.TickSystem();
- application.Tick();
+ m_application.PumpSystemEventLoopUntilEmpty();
+ m_application.TickSystem();
+ m_application.Tick();
EXPECT_THAT(inputChannel->GetState(), Eq(InputChannel::State::Ended));
-
- application.Stop();
}
TEST_F(XcbInputDeviceKeyboardTests, TextEnteredFromXcbKeyPressEvents)
@@ -420,17 +426,13 @@ namespace AzFramework
EXPECT_CALL(textListener, OnInputTextEvent(StrEq("a"), _)).Times(1);
EXPECT_CALL(textListener, OnInputTextEvent(StrEq("A"), _)).Times(1);
- Application application;
- application.Start({}, {});
- AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
+ m_application.Start();
for (int i = 0; i < 4; ++i)
{
- application.PumpSystemEventLoopUntilEmpty();
- application.TickSystem();
- application.Tick();
+ m_application.PumpSystemEventLoopUntilEmpty();
+ m_application.TickSystem();
+ m_application.Tick();
}
-
- application.Stop();
}
} // namespace AzFramework
diff --git a/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbTestApplication.h b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbTestApplication.h
new file mode 100644
index 0000000000..3035a9de74
--- /dev/null
+++ b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbTestApplication.h
@@ -0,0 +1,38 @@
+/*
+ * 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 AzFramework
+{
+ class XcbTestApplication
+ : public Application
+ {
+ public:
+ XcbTestApplication(AZ::u64 enabledGamepadsCount, bool keyboardEnabled, bool motionEnabled, bool mouseEnabled, bool touchEnabled, bool virtualKeyboardEnabled)
+ {
+ auto* settingsRegistry = AZ::SettingsRegistry::Get();
+ settingsRegistry->Set("/O3DE/InputSystem/GamepadsEnabled", enabledGamepadsCount);
+ settingsRegistry->Set("/O3DE/InputSystem/KeyboardEnabled", keyboardEnabled);
+ settingsRegistry->Set("/O3DE/InputSystem/MotionEnabled", motionEnabled);
+ settingsRegistry->Set("/O3DE/InputSystem/MouseEnabled", mouseEnabled);
+ settingsRegistry->Set("/O3DE/InputSystem/TouchEnabled", touchEnabled);
+ settingsRegistry->Set("/O3DE/InputSystem/VirtualKeyboardEnabled", virtualKeyboardEnabled);
+ }
+
+ void Start(const Descriptor& descriptor = {}, const StartupParameters& startupParameters = {}) override
+ {
+ Application::Start(descriptor, startupParameters);
+ AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
+ }
+ };
+} // namespace AzFramework
diff --git a/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/azframework_xcb_tests_files.cmake b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/azframework_xcb_tests_files.cmake
index 762d5d74fe..147fd2bfe1 100644
--- a/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/azframework_xcb_tests_files.cmake
+++ b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/azframework_xcb_tests_files.cmake
@@ -17,4 +17,5 @@ set(FILES
XcbBaseTestFixture.cpp
XcbBaseTestFixture.h
XcbInputDeviceKeyboardTests.cpp
+ XcbTestApplication.h
)
diff --git a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp
index 462de43262..0cce93d751 100644
--- a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp
+++ b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp
@@ -96,6 +96,8 @@ namespace AzGameFramework
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true);
+#else
+ AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false);
#endif
// Update the Runtime file paths in case the "{BootstrapSettingsRootKey}/assets" key was overriden by a setting registry
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry);
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Linux/platform_linux_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Linux/platform_linux_files.cmake
index ec71d7b508..f292c29c3c 100644
--- a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Linux/platform_linux_files.cmake
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Linux/platform_linux_files.cmake
@@ -12,6 +12,7 @@ set(FILES
../../Utilities/QtWindowUtilities_linux.cpp
../../Utilities/ScreenGrabber_linux.cpp
../../../Platform/Linux/AzQtComponents/Components/StyledDockWidget_Linux.cpp
+ ../../../Platform/Linux/AzQtComponents/Utilities/DesktopUtilities_Linux.cpp
../../../Platform/Linux/AzQtComponents/AzQtComponents_Traits_Linux.h
../../../Platform/Linux/AzQtComponents/AzQtComponents_Traits_Platform.h
)
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Mac/platform_mac_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Mac/platform_mac_files.cmake
index 18f9479289..4addf53599 100644
--- a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Mac/platform_mac_files.cmake
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Mac/platform_mac_files.cmake
@@ -12,6 +12,7 @@ set(FILES
../../Utilities/QtWindowUtilities_mac.mm
../../Utilities/ScreenGrabber_mac.mm
../../../Platform/Mac/AzQtComponents/Components/StyledDockWidget_Mac.cpp
+ ../../../Platform/Mac/AzQtComponents/Utilities/DesktopUtilities_Mac.cpp
../../../Platform/Mac/AzQtComponents/AzQtComponents_Traits_Mac.h
../../../Platform/Mac/AzQtComponents/AzQtComponents_Traits_Platform.h
)
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Windows/platform_windows_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Windows/platform_windows_files.cmake
index ca4145ef35..bf0d0bb785 100644
--- a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Windows/platform_windows_files.cmake
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Windows/platform_windows_files.cmake
@@ -9,6 +9,7 @@
set(FILES
../../natvis/qt.natvis
../../../Platform/Windows/AzQtComponents/Utilities/HandleDpiAwareness_Windows.cpp
+ ../../../Platform/Windows/AzQtComponents/Utilities/DesktopUtilities_Windows.cpp
../../Utilities/MouseHider_win.cpp
../../Utilities/QtWindowUtilities_win.cpp
../../Utilities/ScreenGrabber_win.cpp
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake
index 8219ab04b2..4c343b852c 100644
--- a/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake
+++ b/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake
@@ -271,7 +271,6 @@ set(FILES
Utilities/ColorUtilities.h
Utilities/Conversions.h
Utilities/Conversions.cpp
- Utilities/DesktopUtilities.cpp
Utilities/DesktopUtilities.h
Utilities/HandleDpiAwareness.cpp
Utilities/HandleDpiAwareness.h
diff --git a/Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/Utilities/DesktopUtilities_Linux.cpp b/Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/Utilities/DesktopUtilities_Linux.cpp
new file mode 100644
index 0000000000..e4ddaceec7
--- /dev/null
+++ b/Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/Utilities/DesktopUtilities_Linux.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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
+
+namespace AzQtComponents
+{
+ void ShowFileOnDesktop(const QString& path)
+ {
+ const char* defaultNautilusPath = "/usr/bin/nautilus";
+ const char* defaultXdgOpenPath = "/usr/bin/xdg-open";
+
+ // Determine if Nautilus (for Gnome Desktops) is available because it supports opening the file manager
+ // and selecting a specific file
+ bool nautilusAvailable = QFileInfo(defaultNautilusPath).exists();
+
+ QFileInfo pathInfo(path);
+ if (pathInfo.isDir())
+ {
+ QProcess::startDetached(defaultXdgOpenPath, { path });
+ }
+ else
+ {
+ if (nautilusAvailable)
+ {
+ QProcess::startDetached(defaultNautilusPath, { "--select", path });
+ }
+ else
+ {
+ QDir parentDir { pathInfo.dir() };
+ QProcess::startDetached(defaultXdgOpenPath, { parentDir.path() });
+ }
+ }
+ }
+
+ QString fileBrowserActionName()
+ {
+ const char* exploreActionName = "Open in file browser";
+ return QObject::tr(exploreActionName);
+ }
+}
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Utilities/DesktopUtilities.cpp b/Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/Utilities/DesktopUtilities_Mac.cpp
similarity index 67%
rename from Code/Framework/AzQtComponents/AzQtComponents/Utilities/DesktopUtilities.cpp
rename to Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/Utilities/DesktopUtilities_Mac.cpp
index c210f17136..5920dc76c6 100644
--- a/Code/Framework/AzQtComponents/AzQtComponents/Utilities/DesktopUtilities.cpp
+++ b/Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/Utilities/DesktopUtilities_Mac.cpp
@@ -15,21 +15,6 @@ namespace AzQtComponents
{
void ShowFileOnDesktop(const QString& path)
{
-#if defined(AZ_PLATFORM_WINDOWS)
-
- // Launch explorer at the path provided
- QStringList args;
- if (!QFileInfo(path).isDir())
- {
- // Folders are just opened, files are selected
- args << "/select,";
- }
- args << QDir::toNativeSeparators(path);
-
- QProcess::startDetached("explorer", args);
-
-#else
-
if (QFileInfo(path).isDir())
{
QProcess::startDetached("/usr/bin/osascript", { "-e",
@@ -43,19 +28,11 @@ namespace AzQtComponents
QProcess::startDetached("/usr/bin/osascript", { "-e",
QStringLiteral("tell application \"Finder\" to activate") });
-
-#endif
}
QString fileBrowserActionName()
{
-#ifdef AZ_PLATFORM_WINDOWS
- const char* exploreActionName = "Open in Explorer";
-#elif defined(AZ_PLATFORM_MAC)
const char* exploreActionName = "Open in Finder";
-#else
- const char* exploreActionName = "Open in file browser";
-#endif
return QObject::tr(exploreActionName);
}
}
diff --git a/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/Utilities/DesktopUtilities_Windows.cpp b/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/Utilities/DesktopUtilities_Windows.cpp
new file mode 100644
index 0000000000..796e2c0ccf
--- /dev/null
+++ b/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/Utilities/DesktopUtilities_Windows.cpp
@@ -0,0 +1,35 @@
+/*
+ * 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
+
+namespace AzQtComponents
+{
+ void ShowFileOnDesktop(const QString& path)
+ {
+ // Launch explorer at the path provided
+ QStringList args;
+ if (!QFileInfo(path).isDir())
+ {
+ // Folders are just opened, files are selected
+ args << "/select,";
+ }
+ args << QDir::toNativeSeparators(path);
+
+ QProcess::startDetached("explorer", args);
+ }
+
+ QString fileBrowserActionName()
+ {
+ const char* exploreActionName = "Open in Explorer";
+ return QObject::tr(exploreActionName);
+ }
+}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h
index 95940e6dd6..2d7d9dc511 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h
@@ -65,6 +65,9 @@ namespace AzToolsFramework
//! @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 c5649c56df..61b257a189 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp
@@ -102,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())
{
@@ -152,4 +161,40 @@ namespace AzToolsFramework
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 44261979ef..7a11e05096 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h
@@ -48,6 +48,7 @@ namespace AzToolsFramework
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;
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/FocusMode/FocusModeNotificationBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeNotificationBus.h
index ab8629ac85..81f1f7bb3b 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeNotificationBus.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeNotificationBus.h
@@ -28,8 +28,10 @@ namespace AzToolsFramework
//////////////////////////////////////////////////////////////////////////
//! Triggered when the editor focus is changed to a different entity.
- //! @param entityId The entity the focus has been moved to.
- virtual void OnEditorFocusChanged(AZ::EntityId entityId) = 0;
+ //! @param previousFocusEntityId The entity the focus has been moved from.
+ //! @param newFocusEntityId The entity the focus has been moved to.
+ virtual void OnEditorFocusChanged(
+ [[maybe_unused]] AZ::EntityId previousFocusEntityId, [[maybe_unused]] AZ::EntityId newFocusEntityId) {}
protected:
~FocusModeNotifications() = default;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp
index af518afd66..f592c471d0 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp
@@ -71,8 +71,9 @@ namespace AzToolsFramework
return;
}
+ AZ::EntityId previousFocusEntityId = m_focusRoot;
m_focusRoot = entityId;
- FocusModeNotificationBus::Broadcast(&FocusModeNotifications::OnEditorFocusChanged, m_focusRoot);
+ FocusModeNotificationBus::Broadcast(&FocusModeNotifications::OnEditorFocusChanged, previousFocusEntityId, m_focusRoot);
if (auto tracker = AZ::Interface::Get();
tracker != nullptr)
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Picking/Manipulators/ManipulatorBounds.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Picking/Manipulators/ManipulatorBounds.cpp
index 3a7fffb3be..4c7afa2275 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Picking/Manipulators/ManipulatorBounds.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Picking/Manipulators/ManipulatorBounds.cpp
@@ -116,7 +116,7 @@ namespace AzToolsFramework
{
return AZ::Intersect::IntersectRayBox(
rayOrigin, rayDirection, m_center, m_axis1, m_axis2, m_axis3, m_halfExtents.GetX(), m_halfExtents.GetY(),
- m_halfExtents.GetZ(), rayIntersectionDistance) > 0;
+ m_halfExtents.GetZ(), rayIntersectionDistance);
}
void ManipulatorBoundBox::SetShapeData(const BoundRequestShapeBase& shapeData)
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp
index ea0fa55256..a84d6bf706 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp
@@ -262,7 +262,7 @@ namespace AzToolsFramework
if (assetId.IsValid())
{
- asset.Create(assetId, true);
+ asset.Create(assetId, false);
}
}
};
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp
index fcec1edd54..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())
@@ -200,7 +234,7 @@ namespace AzToolsFramework::Prefab
m_instanceFocusVector.clear();
// Focus on the root prefab (AZ::EntityId() will default to it)
- FocusOnOwningPrefab(AZ::EntityId());
+ FocusOnPrefabInstanceOwningEntityId(AZ::EntityId());
}
void PrefabFocusHandler::RefreshInstanceFocusList()
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..081655a166 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
@@ -43,6 +43,12 @@ namespace AzToolsFramework
m_instanceToTemplateInterface = AZ::Interface::Get();
AZ_Assert(m_instanceToTemplateInterface, "PrefabPublicHandler - Could not retrieve instance of InstanceToTemplateInterface");
+ m_prefabFocusInterface = AZ::Interface::Get();
+ AZ_Assert(m_prefabFocusInterface, "Could not get PrefabFocusInterface on PrefabPublicHandler construction.");
+
+ m_prefabFocusPublicInterface = AZ::Interface::Get();
+ AZ_Assert(m_prefabFocusPublicInterface, "Could not get PrefabFocusPublicInterface on PrefabPublicHandler construction.");
+
m_prefabLoaderInterface = AZ::Interface::Get();
AZ_Assert(m_prefabLoaderInterface, "Could not get PrefabLoaderInterface on PrefabPublicHandler construction.");
@@ -257,9 +263,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);
}
}
@@ -551,6 +558,13 @@ namespace AzToolsFramework
PrefabEntityResult PrefabPublicHandler::CreateEntity(AZ::EntityId parentId, const AZ::Vector3& position)
{
+ // If the parent is invalid, parent to the container of the currently focused prefab.
+ if (!parentId.IsValid())
+ {
+ AzFramework::EntityContextId editorEntityContextId = AzToolsFramework::GetEntityContextId();
+ parentId = m_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId);
+ }
+
InstanceOptionalReference owningInstanceOfParentEntity = GetOwnerInstanceByEntityId(parentId);
if (!owningInstanceOfParentEntity)
{
@@ -967,13 +981,13 @@ namespace AzToolsFramework
return AZ::Failure(AZStd::string("No entities to duplicate."));
}
- const EntityIdList entityIdsNoLevelInstance = GenerateEntityIdListWithoutLevelInstance(entityIds);
- if (entityIdsNoLevelInstance.empty())
+ const EntityIdList entityIdsNoFocusContainer = GenerateEntityIdListWithoutFocusedInstanceContainer(entityIds);
+ if (entityIdsNoFocusContainer.empty())
{
- return AZ::Failure(AZStd::string("No entities to duplicate because only instance selected is the level instance."));
+ return AZ::Failure(AZStd::string("No entities to duplicate because only instance selected is the container entity of the focused instance."));
}
- if (!EntitiesBelongToSameInstance(entityIdsNoLevelInstance))
+ if (!EntitiesBelongToSameInstance(entityIdsNoFocusContainer))
{
return AZ::Failure(AZStd::string("Cannot duplicate multiple entities belonging to different instances with one operation."
"Change your selection to contain entities in the same instance."));
@@ -981,7 +995,7 @@ namespace AzToolsFramework
// We've already verified the entities are all owned by the same instance,
// so we can just retrieve our instance from the first entity in the list.
- AZ::EntityId firstEntityIdToDuplicate = entityIdsNoLevelInstance[0];
+ AZ::EntityId firstEntityIdToDuplicate = entityIdsNoFocusContainer[0];
InstanceOptionalReference commonOwningInstance = GetOwnerInstanceByEntityId(firstEntityIdToDuplicate);
if (!commonOwningInstance.has_value())
{
@@ -1001,7 +1015,7 @@ namespace AzToolsFramework
// This will cull out any entities that have ancestors in the list, since we will end up duplicating
// the full nested hierarchy with what is returned from RetrieveAndSortPrefabEntitiesAndInstances
- AzToolsFramework::EntityIdSet duplicationSet = AzToolsFramework::GetCulledEntityHierarchy(entityIdsNoLevelInstance);
+ AzToolsFramework::EntityIdSet duplicationSet = AzToolsFramework::GetCulledEntityHierarchy(entityIdsNoFocusContainer);
AZ_PROFILE_FUNCTION(AzToolsFramework);
@@ -1097,7 +1111,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();
@@ -1105,19 +1119,21 @@ namespace AzToolsFramework
PrefabOperationResult PrefabPublicHandler::DeleteFromInstance(const EntityIdList& entityIds, bool deleteDescendants)
{
- const EntityIdList entityIdsNoLevelInstance = GenerateEntityIdListWithoutLevelInstance(entityIds);
+ // Remove the container entity of the focused prefab from the list, if it is included.
+ const EntityIdList entityIdsNoFocusContainer = GenerateEntityIdListWithoutFocusedInstanceContainer(entityIds);
- if (entityIdsNoLevelInstance.empty())
+ if (entityIdsNoFocusContainer.empty())
{
return AZ::Success();
}
- if (!EntitiesBelongToSameInstance(entityIdsNoLevelInstance))
+ // All entities in this list need to belong to the same prefab instance for the operation to be valid.
+ if (!EntitiesBelongToSameInstance(entityIdsNoFocusContainer))
{
return AZ::Failure(AZStd::string("Cannot delete multiple entities belonging to different instances with one operation."));
}
- AZ::EntityId firstEntityIdToDelete = entityIdsNoLevelInstance[0];
+ AZ::EntityId firstEntityIdToDelete = entityIdsNoFocusContainer[0];
InstanceOptionalReference commonOwningInstance = GetOwnerInstanceByEntityId(firstEntityIdToDelete);
// If the first entity id is a container entity id, then we need to mark its parent as the common owning instance because you
@@ -1127,8 +1143,15 @@ namespace AzToolsFramework
commonOwningInstance = commonOwningInstance->get().GetParentInstance();
}
+ // We only allow explicit deletions for entities inside the currently focused prefab.
+ AzFramework::EntityContextId editorEntityContextId = AzToolsFramework::GetEntityContextId();
+ if (&m_prefabFocusInterface->GetFocusedPrefabInstance(editorEntityContextId)->get() != &commonOwningInstance->get())
+ {
+ return AZ::Failure(AZStd::string("Cannot delete entities belonging to an instance that is not being edited."));
+ }
+
// Retrieve entityList from entityIds
- EntityList inputEntityList = EntityIdListToEntityList(entityIdsNoLevelInstance);
+ EntityList inputEntityList = EntityIdListToEntityList(entityIdsNoFocusContainer);
AZ_PROFILE_FUNCTION(AzToolsFramework);
@@ -1185,7 +1208,7 @@ namespace AzToolsFramework
}
else
{
- for (AZ::EntityId entityId : entityIdsNoLevelInstance)
+ for (AZ::EntityId entityId : entityIdsNoFocusContainer)
{
InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
// If this is the container entity, it actually represents the instance so get its owner
@@ -1226,9 +1249,12 @@ namespace AzToolsFramework
return AZ::Failure(AZStd::string("Cannot detach Prefab Instance with invalid container entity."));
}
- if (IsLevelInstanceContainerEntity(containerEntityId))
+ auto editorEntityContextId = AzFramework::EntityContextId::CreateNull();
+ EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
+
+ if (containerEntityId == m_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId))
{
- return AZ::Failure(AZStd::string("Cannot detach level Prefab Instance."));
+ return AZ::Failure(AZStd::string("Cannot detach focused Prefab Instance."));
}
InstanceOptionalReference owningInstance = GetOwnerInstanceByEntityId(containerEntityId);
@@ -1451,9 +1477,14 @@ namespace AzToolsFramework
AZStd::queue entityQueue;
+ auto editorEntityContextId = AzFramework::EntityContextId::CreateNull();
+ EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
+
+ AZ::EntityId focusedPrefabContainerEntityId =
+ m_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId);
for (auto inputEntity : inputEntities)
{
- if (inputEntity && !IsLevelInstanceContainerEntity(inputEntity->GetId()))
+ if (inputEntity && inputEntity->GetId() != focusedPrefabContainerEntityId)
{
entityQueue.push(inputEntity);
}
@@ -1547,19 +1578,19 @@ namespace AzToolsFramework
return AZ::Success();
}
- EntityIdList PrefabPublicHandler::GenerateEntityIdListWithoutLevelInstance(
+ EntityIdList PrefabPublicHandler::GenerateEntityIdListWithoutFocusedInstanceContainer(
const EntityIdList& entityIds) const
{
- EntityIdList outEntityIds;
- outEntityIds.reserve(entityIds.size()); // Actual size could be smaller.
+ EntityIdList outEntityIds(entityIds);
- for (const AZ::EntityId& entityId : entityIds)
+ AzFramework::EntityContextId editorEntityContextId = AzToolsFramework::GetEntityContextId();
+ AZ::EntityId focusedInstanceContainerEntityId = m_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId);
+
+ if (auto iter = AZStd::find(outEntityIds.begin(), outEntityIds.end(), focusedInstanceContainerEntityId); iter != outEntityIds.end())
{
- if (!IsLevelInstanceContainerEntity(entityId))
- {
- outEntityIds.emplace_back(entityId);
- }
+ outEntityIds.erase(iter);
}
+
return outEntityIds;
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h
index f3c0e67d46..a9dadc3336 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h
@@ -74,7 +74,7 @@ namespace AzToolsFramework
Instance& commonRootEntityOwningInstance,
EntityList& outEntities,
AZStd::vector& outInstances) const;
- EntityIdList GenerateEntityIdListWithoutLevelInstance(const EntityIdList& entityIds) const;
+ EntityIdList GenerateEntityIdListWithoutFocusedInstanceContainer(const EntityIdList& entityIds) const;
InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) const;
bool EntitiesBelongToSameInstance(const EntityIdList& entityIds) const;
@@ -187,6 +187,8 @@ namespace AzToolsFramework
InstanceEntityMapperInterface* m_instanceEntityMapperInterface = nullptr;
InstanceToTemplateInterface* m_instanceToTemplateInterface = nullptr;
+ PrefabFocusInterface* m_prefabFocusInterface = nullptr;
+ PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr;
PrefabLoaderInterface* m_prefabLoaderInterface = nullptr;
PrefabSystemComponentInterface* m_prefabSystemComponentInterface = nullptr;
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/EntityOutlinerTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp
index 4364ae1efc..d3138f5139 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp
@@ -313,7 +313,8 @@ namespace AzToolsFramework
StyledTreeView::StartCustomDrag(indexListSorted, supportedActions);
}
- void EntityOutlinerTreeView::OnEditorFocusChanged([[maybe_unused]] AZ::EntityId entityId)
+ void EntityOutlinerTreeView::OnEditorFocusChanged(
+ [[maybe_unused]] AZ::EntityId previousFocusEntityId, [[maybe_unused]] AZ::EntityId newFocusEntityId)
{
viewport()->repaint();
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx
index 2ddbaaafa9..5d76ec6db2 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx
@@ -64,7 +64,7 @@ namespace AzToolsFramework
void leaveEvent(QEvent* event) override;
// FocusModeNotificationBus overrides ...
- void OnEditorFocusChanged(AZ::EntityId entityId) override;
+ void OnEditorFocusChanged(AZ::EntityId previousFocusEntityId, AZ::EntityId newFocusEntityId) override;
//! Renders the left side of the item: appropriate background, branch lines, icons.
void drawBranches(QPainter* painter, const QRect& rect, const QModelIndex& index) const override;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
index 459b39a290..4d53102edb 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;
}
@@ -552,6 +553,13 @@ namespace AzToolsFramework
return;
}
+ // Do not display the context menu if the item under the mouse cursor is not selectable.
+ if (const QModelIndex& index = m_gui->m_objectTree->indexAt(pos); index.isValid()
+ && (index.flags() & Qt::ItemIsSelectable) == 0)
+ {
+ return;
+ }
+
QMenu* contextMenu = new QMenu(this);
// Populate global context menu.
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
index d4b227c4ff..16e3c047b5 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
@@ -24,11 +24,12 @@
#include
#include
#include
-#include
+#include
+#include
+#include
+#include
#include
#include
-#include
-#include
#include
#include
#include
@@ -39,7 +40,6 @@
#include
#include
-
#include
#include
#include
@@ -56,14 +56,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 +128,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 +147,7 @@ namespace AzToolsFramework
AssetBrowser::AssetBrowserSourceDropBus::Handler::BusDisconnect();
AZ::Interface::Unregister(this);
PrefabInstanceContainerNotificationBus::Handler::BusDisconnect();
+ EditorEventsBus::Handler::BusDisconnect();
EditorContextMenuBus::Handler::BusDisconnect();
}
@@ -175,12 +176,16 @@ namespace AzToolsFramework
AzFramework::ApplicationRequests::Bus::BroadcastResult(
prefabWipFeaturesEnabled, &AzFramework::ApplicationRequests::ArePrefabWipFeaturesEnabled);
+ auto editorEntityContextId = AzFramework::EntityContextId::CreateNull();
+ EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
+
// Create Prefab
{
if (!selectedEntities.empty())
{
- // Hide if the only selected entity is the Level Container
- if (selectedEntities.size() > 1 || !s_prefabPublicInterface->IsLevelInstanceContainerEntity(selectedEntities[0]))
+ // Hide if the only selected entity is the Focused Instance Container
+ if (selectedEntities.size() > 1 ||
+ selectedEntities[0] != s_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId))
{
bool layerInSelection = false;
@@ -245,21 +250,16 @@ namespace AzToolsFramework
if (s_prefabPublicInterface->IsInstanceContainerEntity(selectedEntity))
{
// Edit Prefab
- if (prefabWipFeaturesEnabled)
+ if (prefabWipFeaturesEnabled && !s_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(selectedEntity))
{
- bool beingEdited = s_prefabFocusInterface->IsOwningPrefabBeingFocused(selectedEntity);
+ QAction* editAction = menu->addAction(QObject::tr("Edit Prefab"));
+ editAction->setToolTip(QObject::tr("Edit the prefab in focus mode."));
- if (!beingEdited)
- {
- QAction* editAction = menu->addAction(QObject::tr("Edit Prefab"));
- editAction->setToolTip(QObject::tr("Edit the prefab in focus mode."));
+ QObject::connect(editAction, &QAction::triggered, editAction, [selectedEntity] {
+ ContextMenu_EditPrefab(selectedEntity);
+ });
- QObject::connect(editAction, &QAction::triggered, editAction, [selectedEntity] {
- ContextMenu_EditPrefab(selectedEntity);
- });
-
- itemWasShown = true;
- }
+ itemWasShown = true;
}
// Save Prefab
@@ -288,8 +288,9 @@ namespace AzToolsFramework
QAction* deleteAction = menu->addAction(QObject::tr("Delete"));
QObject::connect(deleteAction, &QAction::triggered, deleteAction, [] { ContextMenu_DeleteSelected(); });
- if (selectedEntities.size() == 0 ||
- (selectedEntities.size() == 1 && s_prefabPublicInterface->IsLevelInstanceContainerEntity(selectedEntities[0])))
+
+ if (selectedEntities.empty() ||
+ (selectedEntities.size() == 1 && selectedEntities[0] == s_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId)))
{
deleteAction->setDisabled(true);
}
@@ -297,22 +298,27 @@ namespace AzToolsFramework
// Detach Prefab
if (selectedEntities.size() == 1)
{
- AZ::EntityId selectedEntity = selectedEntities[0];
+ AZ::EntityId selectedEntityId = selectedEntities[0];
- if (s_prefabPublicInterface->IsInstanceContainerEntity(selectedEntity) &&
- !s_prefabPublicInterface->IsLevelInstanceContainerEntity(selectedEntity))
+ if (s_prefabPublicInterface->IsInstanceContainerEntity(selectedEntityId) &&
+ selectedEntityId != s_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId))
{
QAction* detachPrefabAction = menu->addAction(QObject::tr("Detach Prefab..."));
QObject::connect(
detachPrefabAction, &QAction::triggered, detachPrefabAction,
- [selectedEntity]
+ [selectedEntityId]
{
- ContextMenu_DetachPrefab(selectedEntity);
+ ContextMenu_DetachPrefab(selectedEntityId);
});
}
}
}
+ 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);
@@ -331,13 +337,21 @@ namespace AzToolsFramework
QWidget* activeWindow = QApplication::activeWindow();
const AZStd::string prefabFilesPath = "@projectroot@/Prefabs";
- // Remove Level entity if it's part of the list
-
- auto levelContainerIter =
- AZStd::find(selectedEntities.begin(), selectedEntities.end(), s_prefabPublicInterface->GetLevelInstanceContainerEntityId());
- if (levelContainerIter != selectedEntities.end())
+ // Remove focused instance container entity if it's part of the list
+ auto editorEntityContextId = AzFramework::EntityContextId::CreateNull();
+ EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
+
+ auto focusedContainerIter = AZStd::find(
+ selectedEntities.begin(), selectedEntities.end(),
+ s_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId));
+ if (focusedContainerIter != selectedEntities.end())
{
- selectedEntities.erase(levelContainerIter);
+ selectedEntities.erase(focusedContainerIter);
+ }
+
+ if (selectedEntities.empty())
+ {
+ return;
}
// Set default folder for prefabs
@@ -483,7 +497,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 +1407,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..ccad85e32b 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;
}
@@ -178,12 +178,6 @@ namespace AzToolsFramework
AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value());
- // We hide the root instance container entity from the Outliner, so avoid drawing its full container on children
- if (m_prefabPublicInterface->IsLevelInstanceContainerEntity(entityId))
- {
- return;
- }
-
const QTreeView* outlinerTreeView(qobject_cast(option.widget));
const int ancestorLeft = outlinerTreeView->visualRect(index).left() + (m_prefabBorderThickness / 2) - 1;
const int curveRectSize = m_prefabCapsuleRadius * 2;
@@ -191,7 +185,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 +323,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..d5a0595049 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp
@@ -407,7 +407,7 @@ namespace AzToolsFramework
const AzFramework::CameraState cameraState = GetCameraState(viewportId);
for (size_t entityCacheIndex = 0; entityCacheIndex < entityDataCache.VisibleEntityDataCount(); ++entityCacheIndex)
{
- if (entityDataCache.IsVisibleEntityLocked(entityCacheIndex) || !entityDataCache.IsVisibleEntityVisible(entityCacheIndex))
+ if (!entityDataCache.IsVisibleEntitySelectableInViewport(entityCacheIndex))
{
continue;
}
@@ -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/ViewportSelection/EditorVisibleEntityDataCache.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.cpp
index babc6f972c..328cfc3ae5 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.cpp
@@ -9,7 +9,9 @@
#include "EditorVisibleEntityDataCache.h"
#include
+#include
#include
+#include
#include
#include
@@ -21,13 +23,23 @@ namespace AzToolsFramework
using ComponentEntityAccentType = Components::EditorSelectionAccentSystemComponent::ComponentEntityAccentType;
EntityData() = default;
- EntityData(AZ::EntityId entityId, const AZ::Transform& worldFromLocal, bool locked, bool visible, bool selected, bool iconHidden);
+ EntityData(
+ AZ::EntityId entityId,
+ const AZ::Transform& worldFromLocal,
+ bool locked,
+ bool visible,
+ bool inFocus,
+ bool descendantOfClosedContainer,
+ bool selected,
+ bool iconHidden);
AZ::Transform m_worldFromLocal;
AZ::EntityId m_entityId;
ComponentEntityAccentType m_accent = ComponentEntityAccentType::None;
bool m_locked = false;
bool m_visible = true;
+ bool m_inFocus = true;
+ bool m_descendantOfClosedContainer = false;
bool m_selected = false;
bool m_iconHidden = false;
};
@@ -57,12 +69,16 @@ namespace AzToolsFramework
const AZ::Transform& worldFromLocal,
const bool locked,
const bool visible,
+ const bool inFocus,
+ const bool descendantOfClosedContainer,
const bool selected,
const bool iconHidden)
: m_worldFromLocal(worldFromLocal)
, m_entityId(entityId)
, m_locked(locked)
, m_visible(visible)
+ , m_inFocus(inFocus)
+ , m_descendantOfClosedContainer(descendantOfClosedContainer)
, m_selected(selected)
, m_iconHidden(iconHidden)
{
@@ -106,6 +122,18 @@ namespace AzToolsFramework
bool locked = false;
EditorEntityInfoRequestBus::EventResult(locked, entityId, &EditorEntityInfoRequestBus::Events::IsLocked);
+ bool inFocus = false;
+ if (auto focusModeInterface = AZ::Interface::Get())
+ {
+ inFocus = focusModeInterface->IsInFocusSubTree(entityId);
+ }
+
+ bool descendantOfClosedContainer = false;
+ if (ContainerEntityInterface* containerEntityInterface = AZ::Interface::Get())
+ {
+ descendantOfClosedContainer = containerEntityInterface->IsUnderClosedContainerEntity(entityId);
+ }
+
bool iconHidden = false;
EditorEntityIconComponentRequestBus::EventResult(
iconHidden, entityId, &EditorEntityIconComponentRequests::IsEntityIconHiddenInViewport);
@@ -113,7 +141,7 @@ namespace AzToolsFramework
AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM);
- return { entityId, worldFromLocal, locked, visible, IsSelected(entityId), iconHidden };
+ return { entityId, worldFromLocal, locked, visible, inFocus, descendantOfClosedContainer, IsSelected(entityId), iconHidden };
}
EditorVisibleEntityDataCache::EditorVisibleEntityDataCache()
@@ -126,10 +154,17 @@ namespace AzToolsFramework
EntitySelectionEvents::Bus::Router::BusRouterConnect();
EditorEntityIconComponentNotificationBus::Router::BusRouterConnect();
ToolsApplicationNotificationBus::Handler::BusConnect();
+
+ AzFramework::EntityContextId editorEntityContextId = AzToolsFramework::GetEntityContextId();
+
+ ContainerEntityNotificationBus::Handler::BusConnect(editorEntityContextId);
+ FocusModeNotificationBus::Handler::BusConnect(editorEntityContextId);
}
EditorVisibleEntityDataCache::~EditorVisibleEntityDataCache()
{
+ FocusModeNotificationBus::Handler::BusDisconnect();
+ ContainerEntityNotificationBus::Handler::BusDisconnect();
ToolsApplicationNotificationBus::Handler::BusDisconnect();
EditorEntityIconComponentNotificationBus::Router::BusRouterDisconnect();
EntitySelectionEvents::Bus::Router::BusRouterDisconnect();
@@ -260,7 +295,10 @@ namespace AzToolsFramework
bool EditorVisibleEntityDataCache::IsVisibleEntitySelectableInViewport(size_t index) const
{
- return m_impl->m_visibleEntityDatas[index].m_visible && !m_impl->m_visibleEntityDatas[index].m_locked;
+ return m_impl->m_visibleEntityDatas[index].m_visible
+ && !m_impl->m_visibleEntityDatas[index].m_locked
+ && m_impl->m_visibleEntityDatas[index].m_inFocus
+ && !m_impl->m_visibleEntityDatas[index].m_descendantOfClosedContainer;
}
AZStd::optional EditorVisibleEntityDataCache::GetVisibleEntityIndexFromId(const AZ::EntityId entityId) const
@@ -371,4 +409,72 @@ namespace AzToolsFramework
m_impl->m_visibleEntityDatas[entityIndex.value()].m_iconHidden = iconHidden;
}
}
+
+ void EditorVisibleEntityDataCache::OnContainerEntityStatusChanged(AZ::EntityId entityId, [[maybe_unused]] bool open)
+ {
+ // Get container descendants
+ AzToolsFramework::EntityIdList descendantIds;
+ AZ::TransformBus::EventResult(descendantIds, entityId, &AZ::TransformBus::Events::GetAllDescendants);
+
+ // Update cached values
+ if (auto containerEntityInterface = AZ::Interface