diff --git a/Assets/Editor/Translation/scriptcanvas_en_us.ts b/Assets/Editor/Translation/scriptcanvas_en_us.ts
index 7b8361c879..6d436b7caf 100644
--- a/Assets/Editor/Translation/scriptcanvas_en_us.ts
+++ b/Assets/Editor/Translation/scriptcanvas_en_us.ts
@@ -62164,7 +62164,7 @@ An Entity can be selected by using the pick button, or by dragging an Entity fro
HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_NAME
Simple Type: EntityID C++ Type: const EntityId&
- Entity
+ EntityID
HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_TOOLTIP
@@ -62202,7 +62202,7 @@ An Entity can be selected by using the pick button, or by dragging an Entity fro
HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_NAME
Simple Type: EntityID C++ Type: const EntityId&
- Entity
+ EntityId
HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_TOOLTIP
@@ -81852,7 +81852,7 @@ The element is removed from its current parent and added as a child of the new p
HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_NAME
Simple Type: EntityID C++ Type: const EntityId&
- Entity
+ EntityID
HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_TOOLTIP
@@ -89198,7 +89198,7 @@ The element is removed from its current parent and added as a child of the new p
HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_NAME
Simple Type: EntityID C++ Type: const EntityId&
- Entity
+ EntityID
HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_TOOLTIP
@@ -89236,7 +89236,7 @@ The element is removed from its current parent and added as a child of the new p
HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_NAME
Simple Type: EntityID C++ Type: const EntityId&
- Entity
+ EntityID
HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_TOOLTIP
diff --git a/Assets/Engine/EngineAssets/Slices/DefaultLevelSetup.slice b/Assets/Engine/EngineAssets/Slices/DefaultLevelSetup.slice
index 1b7dfdf40d..b82c482c4f 100644
--- a/Assets/Engine/EngineAssets/Slices/DefaultLevelSetup.slice
+++ b/Assets/Engine/EngineAssets/Slices/DefaultLevelSetup.slice
@@ -145,7 +145,7 @@
-
+
diff --git a/Assets/Engine/Entities/GeomCache.ent b/Assets/Engine/Entities/GeomCache.ent
deleted file mode 100644
index e7a63190c3..0000000000
--- a/Assets/Engine/Entities/GeomCache.ent
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:cf441215a769562f88aa20711aee68dadcbf02597d1e2270547055e8e6aec6a3
-size 77
diff --git a/Assets/Engine/Scripts/Entities/Render/GeomCache.lua b/Assets/Engine/Scripts/Entities/Render/GeomCache.lua
deleted file mode 100644
index b496aecd8d..0000000000
--- a/Assets/Engine/Scripts/Entities/Render/GeomCache.lua
+++ /dev/null
@@ -1,178 +0,0 @@
-----------------------------------------------------------------------------------------------------
---
--- Copyright (c) Contributors to the Open 3D Engine Project.
--- For complete copyright and license terms please see the LICENSE at the root of this distribution.
---
--- SPDX-License-Identifier: Apache-2.0 OR MIT
---
---
---
-----------------------------------------------------------------------------------------------------
-Script.ReloadScript("scripts/Utils/EntityUtils.lua")
-
-GeomCache =
-{
- Properties = {
- geomcacheFile = "EngineAssets/GeomCaches/defaultGeomCache.cax",
- bPlaying = 0,
- fStartTime = 0,
- bLooping = 0,
- objectStandIn = "",
- materialStandInMaterial = "",
- objectFirstFrameStandIn = "",
- materialFirstFrameStandInMaterial = "",
- objectLastFrameStandIn = "",
- materialLastFrameStandInMaterial = "",
- fStandInDistance = 0,
- fStreamInDistance = 0,
- Physics = {
- bPhysicalize = 0,
- }
- },
-
- Editor={
- Icon = "animobject.bmp",
- IconOnTop = 1,
- },
-
- bPlaying = 0,
- currentTime = 0,
- precacheTime = 0,
- bPrecachedOutputTriggered = false,
-}
-
-function GeomCache:OnLoad(table)
- self.currentTime = table.currentTime;
-end
-
-function GeomCache:OnSave(table)
- table.currentTime = self.currentTime;
-end
-
-function GeomCache:OnSpawn()
- self.currentTime = self.Properties.fStartTime;
- self:SetFromProperties();
-end
-
-function GeomCache:OnReset()
- self.currentTime = self.Properties.fStartTime;
- self.bPrecachedOutputTriggered = true;
- self:SetFromProperties();
-end
-
-function GeomCache:SetFromProperties()
- local Properties = self.Properties;
-
- if (Properties.geomcacheFile == "") then
- do return end;
- end
-
- self:LoadGeomCache(0, Properties.geomcacheFile);
-
- self.bPlaying = Properties.bPlaying;
- if (self.bPlaying == 0) then
- self.currentTime = Properties.fStartTime;
- end
-
- self:SetGeomCachePlaybackTime(self.currentTime);
- self:SetGeomCacheParams(Properties.bLooping, Properties.objectStandIn, Properties.materialStandInMaterial, Properties.objectFirstFrameStandIn,
- Properties.materialFirstFrameStandInMaterial, Properties.objectLastFrameStandIn, Properties.materialLastFrameStandInMaterial,
- Properties.fStandInDistance, Properties.fStreamInDistance);
- self:SetGeomCacheStreaming(false, 0);
-
- if (Properties.Physics.bPhysicalize == 1) then
- local tempPhysParams = EntityCommon.TempPhysParams;
- self:Physicalize(0, PE_ARTICULATED, tempPhysParams);
- end
-
- self:Activate(1);
-end
-
-function GeomCache:PhysicalizeThis()
- local Physics = self.Properties.Physics;
- EntityCommon.PhysicalizeRigid(self, 0, Physics, false);
-end
-
-function GeomCache:OnUpdate(dt)
- if (self.bPlaying == 1) then
- self:SetGeomCachePlaybackTime(self.currentTime);
- end
-
- if (self:IsGeomCacheStreaming() and not self.bPrecachedOutputTriggered) then
- local precachedTime = self:GetGeomCachePrecachedTime();
- if (precachedTime >= self.precacheTime) then
- self:ActivateOutput("Precached", true);
- self.bPrecachedOutputTriggered = true;
- end
- end
-
- if (self.bPlaying == 1) then
- self.currentTime = self.currentTime + dt;
- end
-end
-
-function GeomCache:OnPropertyChange()
- self:SetFromProperties();
-end
-
-function GeomCache:Event_Start(sender, val)
- self.bPlaying = 1;
-end
-
-function GeomCache:Event_Stop(sender, value)
- self.bPlaying = 0;
-end
-
-function GeomCache:Event_SetTime(sender, value)
- self.currentTime = value;
-end
-
-function GeomCache:Event_StartStreaming(sender, value)
- self.bPrecachedOutputTriggered = false;
- self:SetGeomCacheStreaming(true, self.currentTime);
-end
-
-function GeomCache:Event_StopStreaming(sender, value)
- self:SetGeomCacheStreaming(false, 0);
-end
-
-function GeomCache:Event_PrecacheTime(sender, value)
- self.precacheTime = value;
-end
-
-function GeomCache:Event_Hide(sender, value)
- self:Hide(1);
-end
-
-function GeomCache:Event_Unhide(sender, value)
- self:Hide(0);
-end
-
-function GeomCache:Event_StopDrawing(sender, value)
- self:SetGeomCacheDrawing(false);
-end
-
-function GeomCache:Event_StartDrawing(sender, value)
- self:SetGeomCacheDrawing(true);
-end
-
-GeomCache.FlowEvents =
-{
- Inputs =
- {
- Start = { GeomCache.Event_Start, "any" },
- Stop = { GeomCache.Event_Stop, "any" },
- SetTime = { GeomCache.Event_SetTime, "float" },
- StartStreaming = { GeomCache.Event_StartStreaming, "any" },
- StopStreaming = { GeomCache.Event_StopStreaming, "any" },
- PrecacheTime = { GeomCache.Event_PrecacheTime, "float" },
- Hide = { GeomCache.Event_Hide, "any" },
- Unhide = { GeomCache.Event_Unhide, "any" },
- StopDrawing = { GeomCache.Event_StopDrawing, "any" },
- StartDrawing = { GeomCache.Event_StartDrawing, "any" },
- },
- Outputs =
- {
- Precached = "bool",
- },
-}
diff --git a/AutomatedTesting/Assets/Physics/Collider_PxMeshAutoAssigned/SphereBot/r0-b_body.fbx.assetinfo b/AutomatedTesting/Assets/Physics/Collider_PxMeshAutoAssigned/SphereBot/R0-B_Body.fbx.assetinfo
similarity index 100%
rename from AutomatedTesting/Assets/Physics/Collider_PxMeshAutoAssigned/SphereBot/r0-b_body.fbx.assetinfo
rename to AutomatedTesting/Assets/Physics/Collider_PxMeshAutoAssigned/SphereBot/R0-B_Body.fbx.assetinfo
diff --git a/AutomatedTesting/Assets/Physics/Collider_PxMeshConvexMeshCollides/SphereBot/r0-b_body.fbx.assetinfo b/AutomatedTesting/Assets/Physics/Collider_PxMeshConvexMeshCollides/SphereBot/R0-B_Body.fbx.assetinfo
similarity index 100%
rename from AutomatedTesting/Assets/Physics/Collider_PxMeshConvexMeshCollides/SphereBot/r0-b_body.fbx.assetinfo
rename to AutomatedTesting/Assets/Physics/Collider_PxMeshConvexMeshCollides/SphereBot/R0-B_Body.fbx.assetinfo
diff --git a/AutomatedTesting/Gem/Code/enabled_gems.cmake b/AutomatedTesting/Gem/Code/enabled_gems.cmake
index e6a4d6ca37..3915fd36da 100644
--- a/AutomatedTesting/Gem/Code/enabled_gems.cmake
+++ b/AutomatedTesting/Gem/Code/enabled_gems.cmake
@@ -54,6 +54,7 @@ set(ENABLED_GEMS
AWSMetrics
PrefabBuilder
AudioSystem
+ Terrain
Profiler
Multiplayer
)
diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt
index bec49185bd..800f347359 100644
--- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt
@@ -56,6 +56,9 @@ add_subdirectory(streaming)
## Smoke ##
add_subdirectory(smoke)
+## Terrain ##
+add_subdirectory(Terrain)
+
## AWS ##
add_subdirectory(AWS)
diff --git a/AutomatedTesting/Gem/PythonTests/Terrain/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/Terrain/CMakeLists.txt
new file mode 100644
index 0000000000..9f8ba06829
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Terrain/CMakeLists.txt
@@ -0,0 +1,24 @@
+#
+# 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
+#
+#
+
+if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
+
+ ly_add_pytest(
+ NAME AutomatedTesting::TerrainTests_Main
+ TEST_SUITE main
+ TEST_SERIAL
+ PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main.py
+ RUNTIME_DEPENDENCIES
+ Legacy::Editor
+ AZ::AssetProcessor
+ AutomatedTesting.Assets
+ COMPONENT
+ Terrain
+ )
+
+endif()
diff --git a/AutomatedTesting/Gem/PythonTests/Terrain/EditorScripts/TerrainPhysicsCollider_ChangesSizeWithAxisAlignedBoxShapeChanges.py b/AutomatedTesting/Gem/PythonTests/Terrain/EditorScripts/TerrainPhysicsCollider_ChangesSizeWithAxisAlignedBoxShapeChanges.py
new file mode 100644
index 0000000000..aba506ea20
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Terrain/EditorScripts/TerrainPhysicsCollider_ChangesSizeWithAxisAlignedBoxShapeChanges.py
@@ -0,0 +1,90 @@
+"""
+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
+"""
+
+#fmt: off
+class Tests():
+ create_test_entity = ("Entity created successfully", "Failed to create Entity")
+ add_axis_aligned_box_shape = ("Axis Aligned Box Shape component added", "Failed to add Axis Aligned Box Shape component")
+ add_terrain_collider = ("Terrain Physics Heightfield Collider component added", "Failed to add a Terrain Physics Heightfield Collider component")
+ box_dimensions_changed = ("Aabb dimensions changed successfully", "Failed change Aabb dimensions")
+ configuration_changed = ("Terrain size changed successfully", "Failed terrain size change")
+ no_errors_and_warnings_found = ("No errors and warnings found", "Found errors and warnings")
+#fmt: on
+
+def TerrainPhysicsCollider_ChangesSizeWithAxisAlignedBoxShapeChanges():
+ """
+ Summary:
+ Test aspects of the TerrainHeightGradientList through the BehaviorContext and the Property Tree.
+
+ Test Steps:
+ Expected Behavior:
+ The Editor is stable there are no warnings or errors.
+
+ Test Steps:
+ 1) Load the base level
+ 2) Create test entity
+ 3) Start the Tracer to catch any errors and warnings
+ 4) Add the Axis Aligned Box Shape and Terrain Physics Heightfield Collider components
+ 5) Change the Axis Aligned Box Shape dimensions
+ 6) Check the Heightfield provider is returning the correct size
+ 7) Verify there are no errors and warnings in the logs
+
+
+ :return: None
+ """
+
+ from editor_python_test_tools.editor_entity_utils import EditorEntity
+ from editor_python_test_tools.utils import TestHelper as helper
+ from editor_python_test_tools.utils import Report, Tracer
+ import azlmbr.legacy.general as general
+ import azlmbr.physics as physics
+ import azlmbr.math as azmath
+ import azlmbr.bus as bus
+ import sys
+ import math
+
+ SET_BOX_X_SIZE = 5.0
+ SET_BOX_Y_SIZE = 6.0
+ EXPECTED_COLUMN_SIZE = SET_BOX_X_SIZE + 1
+ EXPECTED_ROW_SIZE = SET_BOX_Y_SIZE + 1
+ helper.init_idle()
+
+ # 1) Load the level
+ helper.open_level("", "Base")
+
+ # 2) Create test entity
+ test_entity = EditorEntity.create_editor_entity("TestEntity")
+ Report.result(Tests.create_test_entity, test_entity.id.IsValid())
+
+ # 3) Start the Tracer to catch any errors and warnings
+ with Tracer() as section_tracer:
+ # 4) Add the Axis Aligned Box Shape and Terrain Physics Heightfield Collider components
+ aaBoxShape_component = test_entity.add_component("Axis Aligned Box Shape")
+ Report.result(Tests.add_axis_aligned_box_shape, test_entity.has_component("Axis Aligned Box Shape"))
+ terrainPhysics_component = test_entity.add_component("Terrain Physics Heightfield Collider")
+ Report.result(Tests.add_terrain_collider, test_entity.has_component("Terrain Physics Heightfield Collider"))
+
+ # 5) Change the Axis Aligned Box Shape dimensions
+ aaBoxShape_component.set_component_property_value("Axis Aligned Box Shape|Box Configuration|Dimensions", azmath.Vector3(SET_BOX_X_SIZE, SET_BOX_Y_SIZE, 1.0))
+ add_check = aaBoxShape_component.get_component_property_value("Axis Aligned Box Shape|Box Configuration|Dimensions") == azmath.Vector3(SET_BOX_X_SIZE, SET_BOX_Y_SIZE, 1.0)
+ Report.result(Tests.box_dimensions_changed, add_check)
+
+ # 6) Check the Heightfield provider is returning the correct size
+ columns = physics.HeightfieldProviderRequestsBus(bus.Broadcast, "GetHeightfieldGridColumns")
+ rows = physics.HeightfieldProviderRequestsBus(bus.Broadcast, "GetHeightfieldGridRows")
+ Report.result(Tests.configuration_changed, math.isclose(columns, EXPECTED_COLUMN_SIZE) and math.isclose(rows, EXPECTED_ROW_SIZE))
+
+ helper.wait_for_condition(lambda: section_tracer.has_errors or section_tracer.has_asserts, 1.0)
+ for error_info in section_tracer.errors:
+ Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
+ for assert_info in section_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(TerrainPhysicsCollider_ChangesSizeWithAxisAlignedBoxShapeChanges)
diff --git a/AutomatedTesting/Gem/PythonTests/Terrain/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/Terrain/TestSuite_Main.py
new file mode 100644
index 0000000000..620d84d7db
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Terrain/TestSuite_Main.py
@@ -0,0 +1,25 @@
+"""
+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
+
+"""
+
+# This suite consists of all test cases that are passing and have been verified.
+
+import pytest
+import os
+import sys
+
+from ly_test_tools import LAUNCHERS
+from ly_test_tools.o3de.editor_test import EditorTestSuite, EditorSingleTest
+
+@pytest.mark.SUITE_main
+@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
+@pytest.mark.parametrize("project", ["AutomatedTesting"])
+class TestAutomation(EditorTestSuite):
+ #global_extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"]
+
+ class test_AxisAlignedBoxShape_ConfigurationWorks(EditorSingleTest):
+ from .EditorScripts import TerrainPhysicsCollider_ChangesSizeWithAxisAlignedBoxShapeChanges as test_module
diff --git a/AutomatedTesting/Gem/PythonTests/Terrain/__init__.py b/AutomatedTesting/Gem/PythonTests/Terrain/__init__.py
new file mode 100644
index 0000000000..f5193b300e
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Terrain/__init__.py
@@ -0,0 +1,6 @@
+"""
+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
+"""
diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/EntityOutliner_EntityOrdering.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/EntityOutliner_EntityOrdering.py
new file mode 100644
index 0000000000..e4575d4d17
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/EntityOutliner_EntityOrdering.py
@@ -0,0 +1,146 @@
+"""
+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:
+ entities_sorted = (
+ "Entities sorted in the expected order",
+ "Entities sorted in an incorrect order",
+ )
+
+
+def EntityOutliner_EntityOrdering():
+ """
+ Summary:
+ Verify that manual entity ordering in the entity outliner works and is stable.
+
+ Expected Behavior:
+ Several entities are created, some are manually ordered, and their order
+ is maintained, even when new entities are added.
+
+ Test Steps:
+ 1) Open the empty Prefab Base level
+ 2) Add 5 entities to the outliner
+ 3) Move "Entity1" to the top of the order
+ 4) Move "Entity4" to the bottom of the order
+ 5) Add another new entity, ensure the rest of the order is unchanged
+ """
+
+ import editor_python_test_tools.pyside_utils as pyside_utils
+ import azlmbr.legacy.general as general
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import TestHelper as helper
+ from PySide2 import QtCore, QtWidgets, QtGui, QtTest
+
+ # Grab the Editor, Entity Outliner, and Outliner Model
+ editor_window = pyside_utils.get_editor_main_window()
+ entity_outliner = pyside_utils.find_child_by_hierarchy(
+ editor_window, ..., "EntityOutlinerWidgetUI", ..., "m_objectTree"
+ )
+ entity_outliner_model = entity_outliner.model()
+
+ # Get the outliner index for the root prefab container entity
+ def get_root_prefab_container_index():
+ return entity_outliner_model.index(0, 0)
+
+ # Get the outliner index for the top level entity of a given name
+ def index_for_name(name):
+ root_index = get_root_prefab_container_index()
+ for row in range(entity_outliner_model.rowCount(root_index)):
+ row_index = entity_outliner_model.index(row, 0, root_index)
+ if row_index.data() == name:
+ return row_index
+ return None
+
+ # Validate that the outliner top level entity order matches the expected order
+ def verify_entities_sorted(expected_order):
+ actual_order = []
+ root_index = get_root_prefab_container_index()
+ for row in range(entity_outliner_model.rowCount(root_index)):
+ row_index = entity_outliner_model.index(row, 0, root_index)
+ actual_order.append(row_index.data())
+
+ sorted_correctly = actual_order == expected_order
+ Report.result(Tests.entities_sorted, sorted_correctly)
+ if not sorted_correctly:
+ print(f"Expected entity order: {expected_order}")
+ print(f"Actual entity order: {actual_order}")
+
+ # Creates an entity from the outliner context menu
+ def create_entity():
+ pyside_utils.trigger_context_menu_entry(
+ entity_outliner, "Create entity", index=get_root_prefab_container_index()
+ )
+ # Wait a tick after entity creation to let events process
+ general.idle_wait(0.0)
+
+ # Moves an entity (wrapped by move_entity_before and move_entity_after)
+ def _move_entity(source_name, target_name, move_after=False):
+ source_index = index_for_name(source_name)
+ target_index = index_for_name(target_name)
+
+ target_row = target_index.row()
+ if move_after:
+ target_row += 1
+
+ # Generate MIME data and directly inject it into the model instead of
+ # generating mouse click operations, as it's more reliable and we're
+ # testing the underlying drag & drop logic as opposed to Qt's mouse
+ # handling here
+ mime_data = entity_outliner_model.mimeData([source_index])
+ entity_outliner_model.dropMimeData(
+ mime_data, QtCore.Qt.MoveAction, target_row, 0, target_index.parent()
+ )
+ QtWidgets.QApplication.processEvents()
+
+ # Move an entity before another entity in the order by dragging the source above the target
+ move_entity_before = lambda source_name, target_name: _move_entity(
+ source_name, target_name, move_after=False
+ )
+ # Move an entity after another entity in the order by dragging the source beloew the target
+ move_entity_after = lambda source_name, target_name: _move_entity(
+ source_name, target_name, move_after=True
+ )
+
+ expected_order = []
+
+ # 1) Open the empty Prefab Base level
+ helper.init_idle()
+ helper.open_level("Prefab", "Base")
+
+ # 2) Add 5 entities to the outliner
+ ENTITIES_TO_ADD = 5
+ for i in range(ENTITIES_TO_ADD):
+ create_entity()
+
+ # Our new entity should be given a name with a number automatically
+ new_entity = f"Entity{i+1}"
+ # The new entity should be added to the top of its parent entity
+ expected_order = [new_entity] + expected_order
+
+ verify_entities_sorted(expected_order)
+
+ # 3) Move "Entity1" to the top of the order
+ move_entity_before("Entity1", "Entity5")
+ expected_order = ["Entity1", "Entity5", "Entity4", "Entity3", "Entity2"]
+ verify_entities_sorted(expected_order)
+
+ # 4) Move "Entity4" to the bottom of the order
+ move_entity_after("Entity4", "Entity2")
+ expected_order = ["Entity1", "Entity5", "Entity3", "Entity2", "Entity4"]
+ verify_entities_sorted(expected_order)
+
+ # 5) Add another new entity, ensure the rest of the order is unchanged
+ create_entity()
+ expected_order = ["Entity6", "Entity1", "Entity5", "Entity3", "Entity2", "Entity4"]
+ verify_entities_sorted(expected_order)
+
+
+if __name__ == "__main__":
+ from editor_python_test_tools.utils import Report
+
+ Report.start_test(EntityOutliner_EntityOrdering)
diff --git a/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main.py
index 26b254ae71..49069569eb 100644
--- a/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main.py
+++ b/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main.py
@@ -41,3 +41,15 @@ class TestAutomation(TestAutomationBase):
from .EditorScripts import BasicEditorWorkflows_LevelEntityComponentCRUD as test_module
self._run_test(request, workspace, editor, test_module, batch_mode=False, autotest_mode=False,
use_null_renderer=False)
+
+ def test_EntityOutlienr_EntityOrdering(self, request, workspace, editor, launcher_platform):
+ from .EditorScripts import EntityOutliner_EntityOrdering as test_module
+ self._run_test(
+ request,
+ workspace,
+ editor,
+ test_module,
+ batch_mode=False,
+ autotest_mode=True,
+ extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"]
+ )
diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_Editor_NewExistingLevels_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_Editor_NewExistingLevels_Works.py
index 6f654b9107..72e548615c 100644
--- a/AutomatedTesting/Gem/PythonTests/smoke/test_Editor_NewExistingLevels_Works.py
+++ b/AutomatedTesting/Gem/PythonTests/smoke/test_Editor_NewExistingLevels_Works.py
@@ -28,4 +28,4 @@ class TestAutomation(TestAutomationBase):
from . import Editor_NewExistingLevels_Works as test_module
- self._run_test(request, workspace, editor, test_module)
+ self._run_test(request, workspace, editor, test_module, extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=false"])
diff --git a/AutomatedTesting/Levels/Physics/ForceRegion_ImpulsesPxMeshShapedRigidBody/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo b/AutomatedTesting/Levels/Physics/ForceRegion_ImpulsesPxMeshShapedRigidBody/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo
similarity index 100%
rename from AutomatedTesting/Levels/Physics/ForceRegion_ImpulsesPxMeshShapedRigidBody/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo
rename to AutomatedTesting/Levels/Physics/ForceRegion_ImpulsesPxMeshShapedRigidBody/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo
diff --git a/AutomatedTesting/Levels/Physics/ForceRegion_PxMeshShapedForce/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo b/AutomatedTesting/Levels/Physics/ForceRegion_PxMeshShapedForce/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo
similarity index 100%
rename from AutomatedTesting/Levels/Physics/ForceRegion_PxMeshShapedForce/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo
rename to AutomatedTesting/Levels/Physics/ForceRegion_PxMeshShapedForce/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo
diff --git a/AutomatedTesting/Levels/Physics/Material_DefaultMaterialLibraryChangesWork/rin_skeleton_newgeo - copy.fbx.assetinfo b/AutomatedTesting/Levels/Physics/Material_DefaultMaterialLibraryChangesWork/rin_skeleton_newgeo - Copy.fbx.assetinfo
similarity index 100%
rename from AutomatedTesting/Levels/Physics/Material_DefaultMaterialLibraryChangesWork/rin_skeleton_newgeo - copy.fbx.assetinfo
rename to AutomatedTesting/Levels/Physics/Material_DefaultMaterialLibraryChangesWork/rin_skeleton_newgeo - Copy.fbx.assetinfo
diff --git a/AutomatedTesting/Levels/Physics/Physics_WorldBodyBusWorksOnEditorComponents/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo b/AutomatedTesting/Levels/Physics/Physics_WorldBodyBusWorksOnEditorComponents/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo
similarity index 100%
rename from AutomatedTesting/Levels/Physics/Physics_WorldBodyBusWorksOnEditorComponents/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo
rename to AutomatedTesting/Levels/Physics/Physics_WorldBodyBusWorksOnEditorComponents/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo
diff --git a/AutomatedTesting/Levels/Physics/RigidBody_COM_ComputingWorks/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo b/AutomatedTesting/Levels/Physics/RigidBody_COM_ComputingWorks/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo
similarity index 100%
rename from AutomatedTesting/Levels/Physics/RigidBody_COM_ComputingWorks/PhysXSedan/_dev_sedan_r0-b.fbx.assetinfo
rename to AutomatedTesting/Levels/Physics/RigidBody_COM_ComputingWorks/PhysXSedan/_dev_Sedan_r0-b.fbx.assetinfo
diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp
index 5bcb77797c..c74d6ac960 100644
--- a/Code/Editor/CryEdit.cpp
+++ b/Code/Editor/CryEdit.cpp
@@ -1361,16 +1361,6 @@ void CCryEditApp::CompileCriticalAssets() const
assetsInQueueNotifcation.BusDisconnect();
CCryEditApp::OutputStartupMessage(QString("Asset Processor is now ready."));
- // VERY early on, as soon as we can, request that the asset system make sure the following assets take priority over others,
- // so that by the time we ask for them there is a greater likelihood that they're already good to go.
- // these can be loaded later but are still important:
- AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "/texturemsg/");
- AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/materials");
- AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/geomcaches");
- AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/objects");
-
- // some are specifically extra important and will cause issues if missing completely:
- AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::CompileAssetSync, "engineassets/objects/default.cgf");
}
bool CCryEditApp::ConnectToAssetProcessor() const
@@ -3974,9 +3964,8 @@ void CCryEditApp::OpenLUAEditor(const char* files)
}
}
- const char* engineRoot = nullptr;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
- AZ_Assert(engineRoot != nullptr, "Unable to communicate to AzFramework::ApplicationRequests::Bus");
+ AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath();
+ AZ_Assert(!engineRoot.empty(), "Unable to query Engine Path");
AZStd::string_view exePath;
AZ::ComponentApplicationBus::BroadcastResult(exePath, &AZ::ComponentApplicationRequests::GetExecutableFolder);
@@ -3995,7 +3984,7 @@ void CCryEditApp::OpenLUAEditor(const char* files)
#endif
"%s", argumentQuoteString, aznumeric_cast(exePath.size()), exePath.data(), argumentQuoteString);
- AZStd::string processArgs = AZStd::string::format("%s -engine-path \"%s\"", args.c_str(), engineRoot);
+ AZStd::string processArgs = AZStd::string::format("%s -engine-path \"%s\"", args.c_str(), engineRoot.c_str());
StartProcessDetached(process.c_str(), processArgs.c_str());
}
diff --git a/Code/Editor/Include/IFileUtil.h b/Code/Editor/Include/IFileUtil.h
index e179f892d9..036a0bc5ee 100644
--- a/Code/Editor/Include/IFileUtil.h
+++ b/Code/Editor/Include/IFileUtil.h
@@ -60,7 +60,6 @@ struct IFileUtil
EFILE_TYPE_GEOMETRY,
EFILE_TYPE_TEXTURE,
EFILE_TYPE_SOUND,
- EFILE_TYPE_GEOMCACHE,
EFILE_TYPE_LAST,
};
@@ -114,9 +113,7 @@ struct IFileUtil
virtual void ShowInExplorer(const QString& path) = 0;
- virtual bool CompileLuaFile(const char* luaFilename) = 0;
virtual bool ExtractFile(QString& file, bool bMsgBoxAskForExtraction = true, const char* pDestinationFilename = nullptr) = 0;
- virtual void EditTextFile(const char* txtFile, int line = 0, ETextFileType fileType = FILE_TYPE_SCRIPT) = 0;
virtual void EditTextureFile(const char* txtureFile, bool bUseGameFolder) = 0;
//! dcc filename calculation and extraction sub-routines
diff --git a/Code/Editor/Objects/EntityObject.cpp b/Code/Editor/Objects/EntityObject.cpp
index 6e2354998c..b2dfc04102 100644
--- a/Code/Editor/Objects/EntityObject.cpp
+++ b/Code/Editor/Objects/EntityObject.cpp
@@ -956,11 +956,7 @@ void CEntityObject::Serialize(CObjectArchive& ar)
QString attachmentType;
xmlNode->getAttr("AttachmentType", attachmentType);
- if (attachmentType == "GeomCacheNode")
- {
- m_attachmentType = eAT_GeomCacheNode;
- }
- else if (attachmentType == "CharacterBone")
+ if (attachmentType == "CharacterBone")
{
m_attachmentType = eAT_CharacterBone;
}
@@ -987,11 +983,7 @@ void CEntityObject::Serialize(CObjectArchive& ar)
{
if (m_attachmentType != eAT_Pivot)
{
- if (m_attachmentType == eAT_GeomCacheNode)
- {
- xmlNode->setAttr("AttachmentType", "GeomCacheNode");
- }
- else if (m_attachmentType == eAT_CharacterBone)
+ if (m_attachmentType == eAT_CharacterBone)
{
xmlNode->setAttr("AttachmentType", "CharacterBone");
}
@@ -1091,11 +1083,7 @@ XmlNodeRef CEntityObject::Export([[maybe_unused]] const QString& levelPath, XmlN
objNode->setAttr("ParentId", parentEntity->GetEntityId());
if (m_attachmentType != eAT_Pivot)
{
- if (m_attachmentType == eAT_GeomCacheNode)
- {
- objNode->setAttr("AttachmentType", "GeomCacheNode");
- }
- else if (m_attachmentType == eAT_CharacterBone)
+ if (m_attachmentType == eAT_CharacterBone)
{
objNode->setAttr("AttachmentType", "CharacterBone");
}
diff --git a/Code/Editor/Objects/EntityObject.h b/Code/Editor/Objects/EntityObject.h
index dcc6ff7b22..a4f4752b75 100644
--- a/Code/Editor/Objects/EntityObject.h
+++ b/Code/Editor/Objects/EntityObject.h
@@ -131,7 +131,6 @@ public:
enum EAttachmentType
{
eAT_Pivot,
- eAT_GeomCacheNode,
eAT_CharacterBone,
};
diff --git a/Code/Editor/Objects/ObjectManager.cpp b/Code/Editor/Objects/ObjectManager.cpp
index fc9696601d..ae627f4b9d 100644
--- a/Code/Editor/Objects/ObjectManager.cpp
+++ b/Code/Editor/Objects/ObjectManager.cpp
@@ -608,7 +608,7 @@ bool CObjectManager::AddObject(CBaseObject* obj)
if (CEntityObject* entityObj = qobject_cast(obj))
{
CEntityObject::EAttachmentType attachType = entityObj->GetAttachType();
- if (attachType == CEntityObject::EAttachmentType::eAT_GeomCacheNode || attachType == CEntityObject::EAttachmentType::eAT_CharacterBone)
+ if (attachType == CEntityObject::EAttachmentType::eAT_CharacterBone)
{
m_animatedAttachedEntities.insert(entityObj);
}
diff --git a/Code/Editor/TrackView/AtomOutputFrameCapture.cpp b/Code/Editor/TrackView/AtomOutputFrameCapture.cpp
index 94451e6914..5943e3c2d7 100644
--- a/Code/Editor/TrackView/AtomOutputFrameCapture.cpp
+++ b/Code/Editor/TrackView/AtomOutputFrameCapture.cpp
@@ -13,6 +13,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -47,18 +48,42 @@ namespace TrackView
AZ::Name viewName = AZ::Name("MainCamera");
m_view = AZ::RPI::View::CreateView(viewName, AZ::RPI::View::UsageCamera);
m_renderPipeline->SetDefaultView(m_view);
+ m_targetView = scene.GetDefaultRenderPipeline()->GetDefaultView();
+ if (AZ::Render::PostProcessFeatureProcessor* fp = scene.GetFeatureProcessor())
+ {
+ // This will be set again to mimic the active camera in UpdateView
+ fp->SetViewAlias(m_view, m_targetView);
+ }
}
void AtomOutputFrameCapture::DestroyPipeline(AZ::RPI::Scene& scene)
{
+ if (AZ::Render::PostProcessFeatureProcessor* fp = scene.GetFeatureProcessor())
+ {
+ // Remove view alias introduced in CreatePipeline and UpdateView
+ fp->RemoveViewAlias(m_view);
+ }
scene.RemoveRenderPipeline(m_renderPipeline->GetId());
m_passHierarchy.clear();
m_renderPipeline.reset();
m_view.reset();
+ m_targetView.reset();
}
- void AtomOutputFrameCapture::UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection)
+ void AtomOutputFrameCapture::UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection, const AZ::RPI::ViewPtr targetView)
{
+ if (targetView && targetView != m_targetView)
+ {
+ if (AZ::RPI::Scene* scene = SceneFromGameEntityContext())
+ {
+ if (AZ::Render::PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor())
+ {
+ fp->SetViewAlias(m_view, targetView);
+ m_targetView = targetView;
+ }
+ }
+ }
+
m_view->SetCameraTransform(cameraTransform);
m_view->SetViewToClipMatrix(cameraProjection);
}
diff --git a/Code/Editor/TrackView/AtomOutputFrameCapture.h b/Code/Editor/TrackView/AtomOutputFrameCapture.h
index 2686a81c99..4719ab08e5 100644
--- a/Code/Editor/TrackView/AtomOutputFrameCapture.h
+++ b/Code/Editor/TrackView/AtomOutputFrameCapture.h
@@ -39,11 +39,12 @@ namespace TrackView
CaptureFinishedCallback captureFinishedCallback);
//! Update the internal view that is associated with the created pipeline.
- void UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection);
+ void UpdateView(const AZ::Matrix3x4& cameraTransform, const AZ::Matrix4x4& cameraProjection, const AZ::RPI::ViewPtr targetView = nullptr);
private:
AZ::RPI::RenderPipelinePtr m_renderPipeline; //!< The internal render pipeline.
AZ::RPI::ViewPtr m_view; //!< The view associated with the render pipeline.
+ AZ::RPI::ViewPtr m_targetView; //!< The view that this render pipeline will mimic.
AZStd::vector m_passHierarchy; //!< Pass hierarchy (includes pipelineName and CopyToSwapChain).
CaptureFinishedCallback m_captureFinishedCallback; //!< Stored callback called from OnCaptureFinished.
diff --git a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp
index d7901e338a..a796a8ce37 100644
--- a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp
+++ b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp
@@ -16,6 +16,7 @@
#include
#include
+#include
// Qt
#include
@@ -91,9 +92,12 @@ namespace
static void UpdateAtomOutputFrameCaptureView(TrackView::AtomOutputFrameCapture& atomOutputFrameCapture, const int width, const int height)
{
const AZ::EntityId activeCameraEntityId = TrackView::ActiveCameraEntityId();
+ AZ::RPI::ViewPtr view = nullptr;
+ AZ::RPI::ViewProviderBus::EventResult(view, activeCameraEntityId, &AZ::RPI::ViewProvider::GetView);
atomOutputFrameCapture.UpdateView(
TrackView::TransformFromEntityId(activeCameraEntityId),
- TrackView::ProjectionFromCameraEntityId(activeCameraEntityId, static_cast(width), static_cast(height)));
+ TrackView::ProjectionFromCameraEntityId(activeCameraEntityId, aznumeric_cast(width), aznumeric_cast(height)),
+ view);
}
CSequenceBatchRenderDialog::CSequenceBatchRenderDialog(float fps, QWidget* pParent /* = nullptr */)
diff --git a/Code/Editor/Util/FileUtil.cpp b/Code/Editor/Util/FileUtil.cpp
index baca69d628..9f96d45381 100644
--- a/Code/Editor/Util/FileUtil.cpp
+++ b/Code/Editor/Util/FileUtil.cpp
@@ -23,9 +23,9 @@
// AzCore
#include
#include
+#include
// AzFramework
-#include
// AzQtComponents
#include
@@ -54,92 +54,14 @@
#include
#endif
-bool CFileUtil::s_singleFileDlgPref[IFileUtil::EFILE_TYPE_LAST] = { true, true, true, true, true };
-bool CFileUtil::s_multiFileDlgPref[IFileUtil::EFILE_TYPE_LAST] = { true, true, true, true, true };
+bool CFileUtil::s_singleFileDlgPref[IFileUtil::EFILE_TYPE_LAST] = { true, true, true, true };
+bool CFileUtil::s_multiFileDlgPref[IFileUtil::EFILE_TYPE_LAST] = { true, true, true, true };
CAutoRestorePrimaryCDRoot::~CAutoRestorePrimaryCDRoot()
{
QDir::setCurrent(GetIEditor()->GetPrimaryCDFolder());
}
-bool CFileUtil::CompileLuaFile(const char* luaFilename)
-{
- QString luaFile = luaFilename;
-
- if (luaFile.isEmpty())
- {
- return false;
- }
-
- // Check if this file is in Archive.
- {
- CCryFile file;
- if (file.Open(luaFilename, "rb"))
- {
- // Check if in pack.
- if (file.IsInPak())
- {
- return true;
- }
- }
- }
-
- luaFile = Path::GamePathToFullPath(luaFilename);
-
- // First try compiling script and see if it have any errors.
- QString LuaCompiler;
- QString CompilerOutput;
-
- // Create the filepath of the lua compiler
- QString szExeFileName = qApp->applicationFilePath();
- QString exePath = Path::GetPath(szExeFileName);
-
-#if defined(AZ_PLATFORM_WINDOWS)
- const char* luaCompiler = "LuaCompiler.exe";
-#else
- const char* luaCompiler = "lua";
-#endif
- LuaCompiler = Path::AddPathSlash(exePath) + luaCompiler + " ";
-
- AZStd::string path = luaFile.toUtf8().data();
- EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePath, path);
-
- QString finalPath = path.c_str();
- finalPath = "\"" + finalPath + "\"";
-
- // Add the name of the Lua file
- QString cmdLine = LuaCompiler + finalPath;
-
- // Execute the compiler and capture the output
- if (!GetIEditor()->ExecuteConsoleApp(cmdLine, CompilerOutput))
- {
- QMessageBox::critical(QApplication::activeWindow(), QString(), QObject::tr("Error while executing '%1', make sure the file is in" \
- " your Primary CD folder !").arg(luaCompiler));
- return false;
- }
-
- // Check return string
- if (!CompilerOutput.isEmpty())
- {
- // Errors while compiling file.
-
- // Show output from Lua compiler
- if (QMessageBox::critical(QApplication::activeWindow(), QObject::tr("Lua Compiler"),
- QObject::tr("Error output from Lua compiler:\r\n%1\r\nDo you want to edit the file ?").arg(CompilerOutput), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
- {
- int line = 0;
- int index = CompilerOutput.indexOf("at line");
- if (index >= 0)
- {
- azsscanf(CompilerOutput.mid(index).toUtf8().data(), "at line %d", &line);
- }
- // Open the Lua file for editing
- EditTextFile(luaFile.toUtf8().data(), line);
- }
- return false;
- }
- return true;
-}
//////////////////////////////////////////////////////////////////////////
bool CFileUtil::ExtractFile(QString& file, bool bMsgBoxAskForExtraction, const char* pDestinationFilename)
{
@@ -205,7 +127,7 @@ void CFileUtil::EditTextFile(const char* txtFile, int line, IFileUtil::ETextFile
{
QString file = txtFile;
- QString fullPathName = Path::GamePathToFullPath(file);
+ QString fullPathName = Path::GamePathToFullPath(file);
ExtractFile(fullPathName);
QString cmd(fullPathName);
#if defined (AZ_PLATFORM_WINDOWS)
@@ -301,64 +223,6 @@ void CFileUtil::EditTextureFile(const char* textureFile, [[maybe_unused]] bool b
}
}
-//////////////////////////////////////////////////////////////////////////
-bool CFileUtil::EditMayaFile(const char* filepath, const bool bExtractFromPak, const bool bUseGameFolder)
-{
- QString dosFilepath = PathUtil::ToDosPath(filepath).c_str();
- if (bExtractFromPak)
- {
- ExtractFile(dosFilepath);
- }
-
- if (bUseGameFolder)
- {
- const QString sGameFolder = Path::GetEditingGameDataFolder().c_str();
- int nLength = sGameFolder.toUtf8().count();
- if (azstrnicmp(filepath, sGameFolder.toUtf8().data(), nLength) != 0)
- {
- dosFilepath = sGameFolder + '\\' + filepath;
- }
-
- dosFilepath = PathUtil::ToDosPath(dosFilepath.toUtf8().data()).c_str();
- }
-
- const char* engineRoot;
- EBUS_EVENT_RESULT(engineRoot, AzFramework::ApplicationRequests::Bus, GetEngineRoot);
-
- const QString fullPath = QString(engineRoot) + '\\' + dosFilepath;
-
- if (gSettings.animEditor.isEmpty())
- {
- AzQtComponents::ShowFileOnDesktop(fullPath);
- }
- else
- {
- if (!QProcess::startDetached(gSettings.animEditor, { fullPath }))
- {
- CryMessageBox("Can't open the file. You can specify a source editor in Sandbox Preferences or create an association in Windows.", "Cannot open file!", MB_OK | MB_ICONERROR);
- }
- }
- return true;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool CFileUtil::EditFile(const char* filePath, const bool bExtrackFromPak, const bool bUseGameFolder)
-{
- QString extension = filePath;
- extension.remove(0, extension.lastIndexOf('.'));
-
- if (extension.compare(".ma") == 0)
- {
- return EditMayaFile(filePath, bExtrackFromPak, bUseGameFolder);
- }
- else if ((extension.compare(".bspace") == 0) || (extension.compare(".comb") == 0))
- {
- EditTextFile(filePath, 0, IFileUtil::FILE_TYPE_BSPACE);
- return true;
- }
-
- return false;
-}
//////////////////////////////////////////////////////////////////////////
bool CFileUtil::CalculateDccFilename(const QString& assetFilename, QString& dccFilename)
diff --git a/Code/Editor/Util/FileUtil.h b/Code/Editor/Util/FileUtil.h
index 5820c32081..fc0fc942fe 100644
--- a/Code/Editor/Util/FileUtil.h
+++ b/Code/Editor/Util/FileUtil.h
@@ -25,14 +25,9 @@ public:
static void ShowInExplorer(const QString& path);
- // Try to compile the given lua file: returns true if compilation succeeded, false on failure.
- static bool CompileLuaFile(const char* luaFilename);
-
static bool ExtractFile(QString& file, bool bMsgBoxAskForExtraction = true, const char* pDestinationFilename = nullptr);
static void EditTextFile(const char* txtFile, int line = 0, IFileUtil::ETextFileType fileType = IFileUtil::FILE_TYPE_SCRIPT);
static void EditTextureFile(const char* txtureFile, bool bUseGameFolder);
- static bool EditMayaFile(const char* mayaFile, const bool bExtractFromPak, const bool bUseGameFolder);
- static bool EditFile(const char* filePath, const bool bExtrackFromPak, const bool bUseGameFolder);
//! dcc filename calculation and extraction sub-routines
static bool CalculateDccFilename(const QString& assetFilename, QString& dccFilename);
diff --git a/Code/Editor/Util/FileUtil_impl.cpp b/Code/Editor/Util/FileUtil_impl.cpp
index 0dd3a0ca87..28090d28d5 100644
--- a/Code/Editor/Util/FileUtil_impl.cpp
+++ b/Code/Editor/Util/FileUtil_impl.cpp
@@ -20,21 +20,11 @@ void CFileUtil_impl::ShowInExplorer(const QString& path)
CFileUtil::ShowInExplorer(path);
}
-bool CFileUtil_impl::CompileLuaFile(const char* luaFilename)
-{
- return CFileUtil::CompileLuaFile(luaFilename);
-}
-
bool CFileUtil_impl::ExtractFile(QString& file, bool bMsgBoxAskForExtraction, const char* pDestinationFilename)
{
return CFileUtil::ExtractFile(file, bMsgBoxAskForExtraction, pDestinationFilename);
}
-void CFileUtil_impl::EditTextFile(const char* txtFile, int line, ETextFileType fileType)
-{
- CFileUtil::EditTextFile(txtFile, line, fileType);
-}
-
void CFileUtil_impl::EditTextureFile(const char* txtureFile, bool bUseGameFolder)
{
CFileUtil::EditTextureFile(txtureFile, bUseGameFolder);
diff --git a/Code/Editor/Util/FileUtil_impl.h b/Code/Editor/Util/FileUtil_impl.h
index 04d9e829b9..aa8d0bf3b5 100644
--- a/Code/Editor/Util/FileUtil_impl.h
+++ b/Code/Editor/Util/FileUtil_impl.h
@@ -36,9 +36,7 @@ public:
void ShowInExplorer(const QString& path) override;
- bool CompileLuaFile(const char* luaFilename) override;
bool ExtractFile(QString& file, bool bMsgBoxAskForExtraction = true, const char* pDestinationFilename = nullptr) override;
- void EditTextFile(const char* txtFile, int line = 0, ETextFileType fileType = FILE_TYPE_SCRIPT) override;
void EditTextureFile(const char* txtureFile, bool bUseGameFolder) override;
//! dcc filename calculation and extraction sub-routines
diff --git a/Code/Editor/Util/PathUtil.cpp b/Code/Editor/Util/PathUtil.cpp
index ca3481ddae..8b745ee1bc 100644
--- a/Code/Editor/Util/PathUtil.cpp
+++ b/Code/Editor/Util/PathUtil.cpp
@@ -14,7 +14,6 @@
#include
#include
#include // for ebus events
-#include
#include
#include
@@ -175,9 +174,8 @@ namespace Path
//////////////////////////////////////////////////////////////////////////
QString GetEngineRootPath()
{
- const char* engineRoot;
- EBUS_EVENT_RESULT(engineRoot, AzFramework::ApplicationRequests::Bus, GetEngineRoot);
- return QString(engineRoot);
+ const AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath();
+ return QString::fromUtf8(engineRoot.c_str(), static_cast(engineRoot.size()));
}
//////////////////////////////////////////////////////////////////////////
diff --git a/Code/Editor/WelcomeScreen/WelcomeScreenDialog.cpp b/Code/Editor/WelcomeScreen/WelcomeScreenDialog.cpp
index 17f576b5ee..89dfcaffd1 100644
--- a/Code/Editor/WelcomeScreen/WelcomeScreenDialog.cpp
+++ b/Code/Editor/WelcomeScreen/WelcomeScreenDialog.cpp
@@ -25,8 +25,6 @@
#include
-// AzFramework
-#include
// AzToolsFramework
#include
@@ -173,9 +171,6 @@ void WelcomeScreenDialog::SetRecentFileList(RecentFileList* pList)
m_pRecentList = pList;
- const char* engineRoot;
- EBUS_EVENT_RESULT(engineRoot, AzFramework::ApplicationRequests::Bus, GetEngineRoot);
-
auto projectPath = AZ::Utils::GetProjectPath();
QString gamePath{projectPath.c_str()};
Path::ConvertSlashToBackSlash(gamePath);
diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
index ad7e44c2ae..bd225cf634 100644
--- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
+++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
@@ -485,16 +485,6 @@ namespace AZ
constexpr bool executeRegDumpCommands = false;
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
- // Query for the Executable Path using OS specific functions
- CalculateExecutablePath();
-
- // Determine the path to the engine
- CalculateEngineRoot();
-
- // If the current platform returns an engaged optional from Utils::GetDefaultAppRootPath(), that is used
- // for the application root.
- CalculateAppRoot();
-
SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(*m_settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {});
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*m_settingsRegistry);
@@ -614,7 +604,8 @@ namespace AZ
{
AZ_Assert(!m_isStarted, "Component application already started!");
- if (m_engineRoot.empty())
+ using Type = AZ::SettingsRegistryInterface::Type;
+ if (m_settingsRegistry->GetType(SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder) == Type::NoType)
{
ReportBadEngineRoot();
return nullptr;
@@ -1180,6 +1171,24 @@ namespace AZ
return ReflectionEnvironment::GetReflectionManager() ? ReflectionEnvironment::GetReflectionManager()->GetReflectContext() : nullptr;
}
+ /// Returns the path to the engine.
+
+ const char* ComponentApplication::GetEngineRoot() const
+ {
+ static IO::FixedMaxPathString engineRoot;
+ engineRoot.clear();
+ m_settingsRegistry->Get(engineRoot, SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
+ return engineRoot.c_str();
+ }
+
+ const char* ComponentApplication::GetExecutableFolder() const
+ {
+ static IO::FixedMaxPathString exeFolder;
+ exeFolder.clear();
+ m_settingsRegistry->Get(exeFolder, SettingsRegistryMergeUtils::FilePathKey_BinaryFolder);
+ return exeFolder.c_str();
+ }
+
//=========================================================================
// CreateReflectionManager
//=========================================================================
@@ -1485,27 +1494,6 @@ namespace AZ
}
}
- //=========================================================================
- // CalculateExecutablePath
- //=========================================================================
- void ComponentApplication::CalculateExecutablePath()
- {
- m_exeDirectory = Utils::GetExecutableDirectory();
- }
-
- void ComponentApplication::CalculateAppRoot()
- {
- if (AZStd::optional appRootPath = Utils::GetDefaultAppRootPath(); appRootPath)
- {
- m_appRoot = AZStd::move(*appRootPath);
- }
- }
-
- void ComponentApplication::CalculateEngineRoot()
- {
- m_engineRoot = AZ::SettingsRegistryMergeUtils::FindEngineRoot(*m_settingsRegistry).Native();
- }
-
void ComponentApplication::ResolveModulePath([[maybe_unused]] AZ::OSString& modulePath)
{
// No special parsing of the Module Path is done by the Component Application anymore
diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h
index 6df93aff4e..4e551b6c47 100644
--- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h
+++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h
@@ -221,13 +221,10 @@ namespace AZ
BehaviorContext* GetBehaviorContext() override;
/// Returns the json registration context that has been registered with the app, if there is one.
JsonRegistrationContext* GetJsonRegistrationContext() override;
- /// Returns the working root folder that has been registered with the app, if there is one.
- /// It's expected that derived applications will implement an application root.
- const char* GetAppRoot() const override { return m_appRoot.c_str(); }
/// Returns the path to the engine.
- const char* GetEngineRoot() const override { return m_engineRoot.c_str(); }
+ const char* GetEngineRoot() const override;
/// Returns the path to the folder the executable is in.
- const char* GetExecutableFolder() const override { return m_exeDirectory.c_str(); }
+ const char* GetExecutableFolder() const override;
//////////////////////////////////////////////////////////////////////////
/// TickRequestBus
@@ -352,15 +349,6 @@ namespace AZ
/// Adds system components requested by modules and the application to the system entity.
void AddRequiredSystemComponents(AZ::Entity* systemEntity);
- /// Calculates the directory the application executable comes from.
- void CalculateExecutablePath();
-
- /// Calculates the root directory of the engine.
- void CalculateEngineRoot();
-
- /// Deprecated: The term "AppRoot" has no meaning
- void CalculateAppRoot();
-
template
static void NormalizePath(Iterator begin, Iterator end, bool doLowercase = true)
{
@@ -388,9 +376,6 @@ namespace AZ
void* m_fixedMemoryBlock{ nullptr }; //!< Pointer to the memory block allocator, so we can free it OnDestroy.
IAllocatorAllocate* m_osAllocator{ nullptr };
EntitySetType m_entities;
- AZ::IO::FixedMaxPath m_exeDirectory;
- AZ::IO::FixedMaxPath m_engineRoot;
- AZ::IO::FixedMaxPath m_appRoot;
AZ::SettingsRegistryInterface::NotifyEventHandler m_projectPathChangedHandler;
AZ::SettingsRegistryInterface::NotifyEventHandler m_projectNameChangedHandler;
diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplicationBus.h b/Code/Framework/AzCore/AzCore/Component/ComponentApplicationBus.h
index 0c0977384a..feefa95973 100644
--- a/Code/Framework/AzCore/AzCore/Component/ComponentApplicationBus.h
+++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplicationBus.h
@@ -175,10 +175,6 @@ namespace AZ
//! the serializers used by the best-effort json serialization.
virtual class JsonRegistrationContext* GetJsonRegistrationContext() = 0;
- //! Gets the name of the working root folder that was registered with the app.
- //! @return a pointer to the name of the app's root folder, if a root folder was registered.
- virtual const char* GetAppRoot() const = 0;
-
//! Gets the path of the working engine folder that the app is a part of.
//! @return a pointer to the engine path.
virtual const char* GetEngineRoot() const = 0;
diff --git a/Code/Framework/AzCore/AzCore/Math/Vector3.h b/Code/Framework/AzCore/AzCore/Math/Vector3.h
index 821dc8292c..6b7c53266d 100644
--- a/Code/Framework/AzCore/AzCore/Math/Vector3.h
+++ b/Code/Framework/AzCore/AzCore/Math/Vector3.h
@@ -100,7 +100,7 @@ namespace AZ
void Set(float x, float y, float z);
//! Sets components from an array of 3 floats in xyz order.
- void Set(float values[]);
+ void Set(const float values[]);
//! Indexed access using operator(), just for convenience.
float operator()(int32_t index) const;
diff --git a/Code/Framework/AzCore/AzCore/Math/Vector3.inl b/Code/Framework/AzCore/AzCore/Math/Vector3.inl
index 879ade38cf..6371c688b8 100644
--- a/Code/Framework/AzCore/AzCore/Math/Vector3.inl
+++ b/Code/Framework/AzCore/AzCore/Math/Vector3.inl
@@ -186,7 +186,7 @@ namespace AZ
}
- AZ_MATH_INLINE void Vector3::Set(float values[])
+ AZ_MATH_INLINE void Vector3::Set(const float values[])
{
m_value = Simd::Vec3::LoadImmediate(values[0], values[1], values[2]);
}
diff --git a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp
index 3047a2894e..6cba54a17f 100644
--- a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp
+++ b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp
@@ -50,7 +50,12 @@ namespace AZ
if (!s_instance)
{
- s_instance = Environment::FindVariable(NameDictionaryInstanceName);
+ // Because the NameDictionary allocates memory using the AZ::Allocator and it is created
+ // in the executable memory space, it's ownership cannot be transferred to other module memory spaces
+ // Otherwise this could cause the the NameDictionary to be destroyed in static de-init
+ // after the AZ::Allocators have been destroyed
+ // Therefore we supply the isTransferOwnership value of false using CreateVariableEx
+ s_instance = AZ::Environment::CreateVariableEx(NameDictionaryInstanceName, true, false);
}
return s_instance.IsConstructed();
diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp
index 3668ab14fd..975217a131 100644
--- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp
+++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp
@@ -266,7 +266,8 @@ namespace AZ::SettingsRegistryMergeUtils
// Step 3 locate the project root and attempt to find the engine root using the registered engine
// for the project in the project.json file
- AZ::IO::FixedMaxPath projectRoot = FindProjectRoot(settingsRegistry);
+ AZ::IO::FixedMaxPath projectRoot;
+ settingsRegistry.Get(projectRoot.Native(), FilePathKey_ProjectPath);
if (projectRoot.empty())
{
return {};
@@ -668,7 +669,7 @@ namespace AZ::SettingsRegistryMergeUtils
// NOTE: We make the project-path in the BootstrapSettingsRootKey absolute first
AZ::IO::FixedMaxPath projectPath = FindProjectRoot(registry);
- if (constexpr auto projectPathKey = FixedValueString(BootstrapSettingsRootKey) + "/project_path";
+ if ([[maybe_unused]] constexpr auto projectPathKey = FixedValueString(BootstrapSettingsRootKey) + "/project_path";
!projectPath.empty())
{
if (projectPath.IsRelative())
@@ -693,6 +694,7 @@ namespace AZ::SettingsRegistryMergeUtils
R"(Project path isn't set in the Settings Registry at "%.*s".)"
" Project-related filepaths will be set relative to the executable directory\n",
AZ_STRING_ARG(projectPathKey));
+ projectPath = exePath;
registry.Set(FilePathKey_ProjectPath, exePath.Native());
}
diff --git a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp
index ff30291a70..a953d53c33 100644
--- a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp
+++ b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.cpp
@@ -1427,26 +1427,36 @@ namespace AZ
namespace AssetPath
{
- void CalculateBranchToken(const AZStd::string& appRootPath, AZStd::string& token)
+ namespace Internal
{
- // Normalize the token to prepare for CRC32 calculation
- AZStd::string normalized = appRootPath;
+ AZ::u32 CalculateBranchTokenHash(AZStd::string_view engineRootPath)
+ {
+ // Normalize the token to prepare for CRC32 calculation
+ auto NormalizeEnginePath = [](const char element) -> char
+ {
+ // Substitute path separators with '_' and lower case
+ return element == AZ::IO::WindowsPathSeparator || element == AZ::IO::PosixPathSeparator
+ ? '_' : static_cast(std::tolower(element));
+ };
- // Strip out any trailing path separators
- AZ::StringFunc::Strip(normalized, AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING AZ_WRONG_FILESYSTEM_SEPARATOR_STRING,false, false, true);
+ // Trim off trailing path separators
+ engineRootPath = RStrip(engineRootPath, AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR);
+ AZ::IO::FixedMaxPathString enginePath;
+ AZStd::transform(engineRootPath.begin(), engineRootPath.end(),
+ AZStd::back_inserter(enginePath), AZStd::move(NormalizeEnginePath));
- // Lower case always
- AZStd::to_lower(normalized.begin(), normalized.end());
-
- // Substitute path separators with '_'
- AZStd::replace(normalized.begin(), normalized.end(), '\\', '_');
- AZStd::replace(normalized.begin(), normalized.end(), '/', '_');
-
- // Perform the CRC32 calculation
- const AZ::Crc32 branchTokenCrc(normalized.c_str(), normalized.size(), true);
- char branchToken[12];
- azsnprintf(branchToken, AZ_ARRAY_SIZE(branchToken), "0x%08X", static_cast(branchTokenCrc));
- token = AZStd::string(branchToken);
+ // Perform the CRC32 calculation
+ constexpr bool forceLowercase = true;
+ return static_cast(AZ::Crc32(enginePath.c_str(), enginePath.size(), forceLowercase));
+ }
+ }
+ void CalculateBranchToken(AZStd::string_view engineRootPath, AZStd::string& token)
+ {
+ token = AZStd::string::format("0x%08X", Internal::CalculateBranchTokenHash(engineRootPath));
+ }
+ void CalculateBranchToken(AZStd::string_view engineRootPath, AZ::IO::FixedMaxPathString& token)
+ {
+ token = AZ::IO::FixedMaxPathString::format("0x%08X", Internal::CalculateBranchTokenHash(engineRootPath));
}
}
diff --git a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h
index 1e651afc93..55236a0fff 100644
--- a/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h
+++ b/Code/Framework/AzCore/AzCore/StringFunc/StringFunc.h
@@ -485,10 +485,11 @@ namespace AZ
//! CalculateBranchToken
/*! Calculate the branch token that is used for asset processor connection negotiations
*
- * \param appRootPath - The absolute path of the app root to base the token calculation on
+ * \param engineRootPath - The absolute path to the engine root to base the token calculation on
* \param token - The result of the branch token calculation
*/
- void CalculateBranchToken(const AZStd::string& appRootPath, AZStd::string& token);
+ void CalculateBranchToken(AZStd::string_view engineRootPath, AZStd::string& token);
+ void CalculateBranchToken(AZStd::string_view engineRootPath, AZ::IO::FixedMaxPathString& token);
}
//////////////////////////////////////////////////////////////////////////
diff --git a/Code/Framework/AzCore/AzCore/UnitTest/MockComponentApplication.h b/Code/Framework/AzCore/AzCore/UnitTest/MockComponentApplication.h
index 8f069da9dd..190fa09cb7 100644
--- a/Code/Framework/AzCore/AzCore/UnitTest/MockComponentApplication.h
+++ b/Code/Framework/AzCore/AzCore/UnitTest/MockComponentApplication.h
@@ -41,7 +41,6 @@ namespace UnitTest
MOCK_METHOD0(GetSerializeContext, AZ::SerializeContext* ());
MOCK_METHOD0(GetJsonRegistrationContext, AZ::JsonRegistrationContext* ());
MOCK_METHOD0(GetBehaviorContext, AZ::BehaviorContext* ());
- MOCK_CONST_METHOD0(GetAppRoot, const char* ());
MOCK_CONST_METHOD0(GetEngineRoot, const char* ());
MOCK_CONST_METHOD0(GetExecutableFolder, const char* ());
MOCK_CONST_METHOD1(QueryApplicationType, void(AZ::ApplicationTypeQuery&));
diff --git a/Code/Framework/AzCore/Tests/BehaviorContextFixture.h b/Code/Framework/AzCore/Tests/BehaviorContextFixture.h
index 1895f2e35b..3c6d48add7 100644
--- a/Code/Framework/AzCore/Tests/BehaviorContextFixture.h
+++ b/Code/Framework/AzCore/Tests/BehaviorContextFixture.h
@@ -59,7 +59,6 @@ namespace UnitTest
AZ::SerializeContext* GetSerializeContext() override { return nullptr; }
AZ::BehaviorContext* GetBehaviorContext() override { return m_behaviorContext; }
AZ::JsonRegistrationContext* GetJsonRegistrationContext() override { return nullptr; }
- const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
diff --git a/Code/Framework/AzCore/Tests/Components.cpp b/Code/Framework/AzCore/Tests/Components.cpp
index 55b1c193b3..013d998c52 100644
--- a/Code/Framework/AzCore/Tests/Components.cpp
+++ b/Code/Framework/AzCore/Tests/Components.cpp
@@ -1060,26 +1060,21 @@ namespace UnitTest
/**
* UserSettingsComponent test
*/
- class UserSettingsTestApp
- : public ComponentApplication
- , public UserSettingsFileLocatorBus::Handler
- {
- public:
- void SetExecutableFolder(const char* path)
- {
- m_exeDirectory = path;
- }
-
+ class UserSettingsTestApp
+ : public ComponentApplication
+ , public UserSettingsFileLocatorBus::Handler
+ {
+ public:
AZStd::string ResolveFilePath(u32 providerId) override
{
AZStd::string filePath;
if (providerId == UserSettings::CT_GLOBAL)
{
- filePath = (m_exeDirectory / "GlobalUserSettings.xml").String();
+ filePath = (AZ::IO::Path(GetTestFolderPath()) / "GlobalUserSettings.xml").Native();
}
else if (providerId == UserSettings::CT_LOCAL)
{
- filePath = (m_exeDirectory / "LocalUserSettings.xml").String();
+ filePath = (AZ::IO::Path(GetTestFolderPath()) / "LocalUserSettings.xml").Native();
}
return filePath;
}
@@ -1117,7 +1112,6 @@ namespace UnitTest
ComponentApplication::Descriptor appDesc;
appDesc.m_memoryBlocksByteSize = 10 * 1024 * 1024;
Entity* systemEntity = app.Create(appDesc);
- app.SetExecutableFolder(GetTestFolderPath().c_str());
app.UserSettingsFileLocatorBus::Handler::BusConnect();
// Make sure user settings file does not exist at this point
diff --git a/Code/Framework/AzCore/Tests/Serialization.cpp b/Code/Framework/AzCore/Tests/Serialization.cpp
index f1d5edc490..219744a480 100644
--- a/Code/Framework/AzCore/Tests/Serialization.cpp
+++ b/Code/Framework/AzCore/Tests/Serialization.cpp
@@ -1240,7 +1240,6 @@ namespace UnitTest
SerializeContext* GetSerializeContext() override { return m_serializeContext.get(); }
BehaviorContext* GetBehaviorContext() override { return nullptr; }
JsonRegistrationContext* GetJsonRegistrationContext() override { return nullptr; }
- const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
diff --git a/Code/Framework/AzFramework/AzFramework/API/ApplicationAPI.h b/Code/Framework/AzFramework/AzFramework/API/ApplicationAPI.h
index 1c5db0a82b..e536082d61 100644
--- a/Code/Framework/AzFramework/AzFramework/API/ApplicationAPI.h
+++ b/Code/Framework/AzFramework/AzFramework/API/ApplicationAPI.h
@@ -67,12 +67,6 @@ namespace AzFramework
/// Make path relative to the provided root.
virtual void MakePathRelative(AZStd::string& /*fullPath*/, const char* /*rootPath*/) {}
- /// Gets the engine root path where the modules for the current engine are located.
- virtual const char* GetEngineRoot() const { return nullptr; }
-
- /// Retrieves the app root path for the application.
- virtual const char* GetAppRoot() const { return nullptr; }
-
/// Get the Command Line arguments passed in.
virtual const CommandLine* GetCommandLine() { return nullptr; }
diff --git a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp
index 323e834413..768ef1f0b6 100644
--- a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp
@@ -69,6 +69,7 @@
#include
#include
#include
+#include
#include "Application.h"
#include
@@ -224,13 +225,6 @@ namespace AzFramework
}
}
- void Application::PreModuleLoad()
- {
- SetRootPath(RootPathType::EngineRoot, m_engineRoot.c_str());
- AZ_TracePrintf(s_azFrameworkWarningWindow, "Engine Path: %s\n", m_engineRoot.c_str());
- }
-
-
void Application::Stop()
{
if (m_isStarted)
@@ -318,6 +312,8 @@ namespace AzFramework
AzFramework::SurfaceData::SurfaceTagWeight::Reflect(context);
AzFramework::SurfaceData::SurfacePoint::Reflect(context);
AzFramework::Terrain::TerrainDataRequests::Reflect(context);
+ Physics::HeightfieldProviderRequests::Reflect(context);
+ Physics::HeightMaterialPoint::Reflect(context);
if (AZ::SerializeContext* serializeContext = azrtti_cast(context))
{
@@ -394,11 +390,6 @@ namespace AzFramework
outModules.emplace_back(aznew AzFrameworkModule());
}
- const char* Application::GetAppRoot() const
- {
- return m_appRoot.c_str();
- }
-
const char* Application::GetCurrentConfigurationName() const
{
#if defined(_RELEASE)
@@ -434,19 +425,19 @@ namespace AzFramework
void Application::ResolveEnginePath(AZStd::string& engineRelativePath) const
{
- AZ::IO::FixedMaxPath fullPath = m_engineRoot / engineRelativePath;
+ auto fullPath = AZ::IO::FixedMaxPath(GetEngineRoot()) / engineRelativePath;
engineRelativePath = fullPath.String();
}
void Application::CalculateBranchTokenForEngineRoot(AZStd::string& token) const
{
- AzFramework::StringFunc::AssetPath::CalculateBranchToken(m_engineRoot.String(), token);
+ AZ::StringFunc::AssetPath::CalculateBranchToken(GetEngineRoot(), token);
}
////////////////////////////////////////////////////////////////////////////
void Application::MakePathRootRelative(AZStd::string& fullPath)
{
- MakePathRelative(fullPath, m_engineRoot.c_str());
+ MakePathRelative(fullPath, GetEngineRoot());
}
////////////////////////////////////////////////////////////////////////////
@@ -582,30 +573,6 @@ namespace AzFramework
}
}
- void Application::SetRootPath(RootPathType type, const char* source)
- {
- [[maybe_unused]] const size_t sourceLen = strlen(source);
-
- // Copy the source path to the intended root path and correct the path separators as well
- switch (type)
- {
- case RootPathType::AppRoot:
- {
- AZ_Assert(sourceLen < m_appRoot.Native().max_size(), "String overflow for App Root: %s", source);
- m_appRoot = AZ::IO::PathView(source).LexicallyNormal();
- }
- break;
- case RootPathType::EngineRoot:
- {
- AZ_Assert(sourceLen < m_engineRoot.Native().max_size(), "String overflow for Engine Root: %s", source);
- m_engineRoot = AZ::IO::PathView(source).LexicallyNormal();
- }
- break;
- default:
- AZ_Assert(false, "Invalid RootPathType (%d)", static_cast(type));
- }
- }
-
struct DeprecatedAliasesKeyVisitor
: AZ::SettingsRegistryInterface::Visitor
{
diff --git a/Code/Framework/AzFramework/AzFramework/Application/Application.h b/Code/Framework/AzFramework/AzFramework/Application/Application.h
index c6b1dfeaae..a318ede4a2 100644
--- a/Code/Framework/AzFramework/AzFramework/Application/Application.h
+++ b/Code/Framework/AzFramework/AzFramework/Application/Application.h
@@ -95,8 +95,6 @@ namespace AzFramework
//////////////////////////////////////////////////////////////////////////
//! ApplicationRequests::Bus::Handler
- const char* GetEngineRoot() const override { return m_engineRoot.c_str(); }
- const char* GetAppRoot() const override;
void ResolveEnginePath(AZStd::string& engineRelativePath) const override;
void CalculateBranchTokenForEngineRoot(AZStd::string& token) const override;
bool IsPrefabSystemEnabled() const override;
@@ -146,8 +144,6 @@ namespace AzFramework
*/
void SetFileIOAliases();
- void PreModuleLoad() override;
-
//////////////////////////////////////////////////////////////////////////
//! AZ::ComponentApplication
void RegisterCoreComponents() override;
@@ -181,13 +177,7 @@ namespace AzFramework
bool m_ownsConsole = false;
bool m_exitMainLoopRequested = false;
-
- enum class RootPathType
- {
- AppRoot,
- EngineRoot
- };
- void SetRootPath(RootPathType type, const char* source);
+
};
} // namespace AzFramework
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/HeightfieldProviderBus.cpp b/Code/Framework/AzFramework/AzFramework/Physics/HeightfieldProviderBus.cpp
new file mode 100644
index 0000000000..38fac9655c
--- /dev/null
+++ b/Code/Framework/AzFramework/AzFramework/Physics/HeightfieldProviderBus.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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 "HeightfieldProviderBus.h"
+#include
+#include
+#include
+
+namespace Physics
+{
+ void HeightfieldProviderRequests::Reflect(AZ::ReflectContext* context)
+ {
+ if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context))
+ {
+ behaviorContext->EBus("HeightfieldProviderRequestsBus")
+ ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
+ ->Attribute(AZ::Script::Attributes::Module, "physics")
+ ->Attribute(AZ::Script::Attributes::Category, "PhysX")
+ ->Event("GetHeightfieldGridSpacing", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldGridSpacing)
+ ->Event("GetHeightfieldAabb", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldAabb)
+ ->Event("GetHeightfieldTransform", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldTransform)
+ ->Event("GetMaterialList", &Physics::HeightfieldProviderRequestsBus::Events::GetMaterialList)
+ ->Event("GetHeights", &Physics::HeightfieldProviderRequestsBus::Events::GetHeights)
+ ->Event("GetHeightsAndMaterials", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightsAndMaterials)
+ ->Event("GetHeightfieldMinHeight", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldMinHeight)
+ ->Event("GetHeightfieldMaxHeight", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldMaxHeight)
+ ->Event("GetHeightfieldGridColumns", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldGridColumns)
+ ->Event("GetHeightfieldGridRows", &Physics::HeightfieldProviderRequestsBus::Events::GetHeightfieldGridRows)
+ ;
+ }
+ }
+
+ void HeightMaterialPoint::Reflect(AZ::ReflectContext* context)
+ {
+ if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context))
+ {
+ behaviorContext->Class()->Attribute(AZ::Script::Attributes::Category, "Physics");
+ }
+ }
+
+} // namespace Physics
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/HeightfieldProviderBus.h b/Code/Framework/AzFramework/AzFramework/Physics/HeightfieldProviderBus.h
index 73523ee1ba..da361f0a2b 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/HeightfieldProviderBus.h
+++ b/Code/Framework/AzFramework/AzFramework/Physics/HeightfieldProviderBus.h
@@ -26,10 +26,25 @@ namespace Physics
struct HeightMaterialPoint
{
+ HeightMaterialPoint(
+ float height = 0.0f, QuadMeshType type = QuadMeshType::SubdivideUpperLeftToBottomRight, uint8_t index = 0)
+ : m_height(height)
+ , m_quadMeshType(type)
+ , m_materialIndex(index)
+ , m_padding(0)
+ {
+ }
+
+ virtual ~HeightMaterialPoint() = default;
+
+ static void Reflect(AZ::ReflectContext* context);
+
+ AZ_RTTI(HeightMaterialPoint, "{DF167ED4-24E6-4F7B-8AB7-42622F7DBAD3}");
float m_height{ 0.0f }; //!< Holds the height of this point in the heightfield relative to the heightfield entity location.
QuadMeshType m_quadMeshType{ QuadMeshType::SubdivideUpperLeftToBottomRight }; //!< By default, create two triangles like this |\|, where this point is in the upper left corner.
uint8_t m_materialIndex{ 0 }; //!< The surface material index for the upper left corner of this quad.
uint16_t m_padding{ 0 }; //!< available for future use.
+
};
//! An interface to provide heightfield values.
@@ -37,6 +52,8 @@ namespace Physics
: public AZ::ComponentBus
{
public:
+ static void Reflect(AZ::ReflectContext* context);
+
//! Returns the distance between each height in the map.
//! @return Vector containing Column Spacing, Rows Spacing.
virtual AZ::Vector2 GetHeightfieldGridSpacing() const = 0;
@@ -46,11 +63,27 @@ namespace Physics
//! @param numRows contains the size of the grid in the y direction.
virtual void GetHeightfieldGridSize(int32_t& numColumns, int32_t& numRows) const = 0;
+ //! Returns the height field gridsize columns.
+ //! @return the size of the grid in the x direction.
+ virtual int32_t GetHeightfieldGridColumns() const = 0;
+
+ //! Returns the height field gridsize rows.
+ //! @return the size of the grid in the y direction.
+ virtual int32_t GetHeightfieldGridRows() const = 0;
+
//! Returns the height field min and max height bounds.
//! @param minHeightBounds contains the minimum height that the heightfield can contain.
//! @param maxHeightBounds contains the maximum height that the heightfield can contain.
virtual void GetHeightfieldHeightBounds(float& minHeightBounds, float& maxHeightBounds) const = 0;
+ //! Returns the height field min height bounds.
+ //! @return the minimum height that the heightfield can contain.
+ virtual float GetHeightfieldMinHeight() const = 0;
+
+ //! Returns the height field max height bounds.
+ //! @return the maximum height that the heightfield can contain.
+ virtual float GetHeightfieldMaxHeight() const = 0;
+
//! Returns the AABB of the heightfield.
//! This is provided separately from the shape AABB because the heightfield might choose to modify the AABB bounds.
//! @return AABB of the heightfield.
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Material.cpp b/Code/Framework/AzFramework/AzFramework/Physics/Material.cpp
index 222bc48dda..d78d4e0943 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/Material.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Physics/Material.cpp
@@ -360,6 +360,11 @@ namespace Physics
->Field("MaterialId", &Physics::MaterialId::m_id)
;
}
+
+ if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context))
+ {
+ behaviorContext->Class()->Attribute(AZ::Script::Attributes::Category, "Physics");
+ }
}
MaterialId MaterialId::Create()
diff --git a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake
index 22fbddb39a..16e00349fe 100644
--- a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake
+++ b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake
@@ -229,6 +229,7 @@ set(FILES
Physics/Configuration/SystemConfiguration.h
Physics/Configuration/SystemConfiguration.cpp
Physics/HeightfieldProviderBus.h
+ Physics/HeightfieldProviderBus.cpp
Physics/SimulatedBodies/RigidBody.h
Physics/SimulatedBodies/RigidBody.cpp
Physics/SimulatedBodies/StaticRigidBody.h
diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceMouse.h b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceMouse.h
index a69a8a9ec5..f5b805a7a5 100644
--- a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceMouse.h
+++ b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceMouse.h
@@ -6,6 +6,8 @@
*
*/
+#pragma once
+
#include
#include
#include
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetUtils.cpp
index 139bbb563c..6fd881dbb9 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetUtils.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetUtils.cpp
@@ -14,7 +14,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -205,7 +205,7 @@ namespace AzToolsFramework::AssetUtils
return platformConfigFilePathsAdded;
}
- AZStd::vector GetConfigFiles(AZStd::string_view engineRoot, AZStd::string_view assetRoot, AZStd::string_view projectPath,
+ AZStd::vector GetConfigFiles(AZStd::string_view engineRoot, AZStd::string_view projectPath,
bool addPlatformConfigs, bool addGemsConfigs, AZ::SettingsRegistryInterface* settingsRegistry)
{
constexpr const char* AssetProcessorGamePlatformConfigFileName = "AssetProcessorGamePlatformConfig.ini";
@@ -232,14 +232,13 @@ namespace AzToolsFramework::AssetUtils
Internal::AddGemConfigFiles(gemInfoList, configFiles);
}
- AZ::IO::Path assetRootDir(assetRoot);
- assetRootDir /= projectPath;
+ AZ::IO::Path projectRoot(projectPath);
- AZ::IO::Path projectConfigFile = assetRootDir / AssetProcessorGamePlatformConfigFileName;
+ AZ::IO::Path projectConfigFile = projectRoot / AssetProcessorGamePlatformConfigFileName;
configFiles.push_back(projectConfigFile);
// Add a file entry for the Project AssetProcessor setreg file
- projectConfigFile = assetRootDir / AssetProcessorGamePlatformConfigSetreg;
+ projectConfigFile = projectRoot / AssetProcessorGamePlatformConfigSetreg;
configFiles.push_back(projectConfigFile);
return configFiles;
@@ -251,10 +250,10 @@ namespace AzToolsFramework::AssetUtils
AZStd::vector tokens;
AZ::StringFunc::Tokenize(relPathFromRoot.c_str(), tokens, AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING);
- AZStd::string validatedPath;
+ AZ::IO::FixedMaxPath validatedPath;
if (rootPath.empty())
{
- AzFramework::ApplicationRequests::Bus::BroadcastResult(validatedPath, &AzFramework::ApplicationRequests::GetEngineRoot);
+ validatedPath = AZ::Utils::GetEnginePath();
}
else
{
@@ -299,10 +298,7 @@ namespace AzToolsFramework::AssetUtils
break;
}
- AZStd::string absoluteFilePath;
- AZ::StringFunc::Path::ConstructFull(validatedPath.c_str(), element.c_str(), absoluteFilePath);
-
- validatedPath = absoluteFilePath; // go one step deeper.
+ validatedPath /= element; // go one step deeper.
}
if (success)
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetUtils.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetUtils.h
index 39aab4d3fb..31ee9dcf60 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetUtils.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetUtils.h
@@ -40,7 +40,7 @@ namespace AzToolsFramework::AssetUtils
//! Also note that if the project has any "game project gems", then those will also be inserted last,
//! and thus have a higher priority than the root or non - project gems.
//! Also note that the game project could be in a different location to the engine therefore we need the assetRoot param.
- AZStd::vector GetConfigFiles(AZStd::string_view engineRoot, AZStd::string_view assetRoot, AZStd::string_view projectPath,
+ AZStd::vector GetConfigFiles(AZStd::string_view engineRoot, AZStd::string_view projectPath,
bool addPlatformConfigs = true, bool addGemsConfigs = true, AZ::SettingsRegistryInterface* settingsRegistry = nullptr);
//! A utility function which checks the given path starting at the root and updates the relative path to be the actual case correct path.
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp
index acf935e6dc..c6772ea2d7 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp
@@ -20,7 +20,7 @@ AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option")
AZ_POP_DISABLE_WARNING
AZ_CVAR(
- bool, ed_useNewAssetBrowserTableView, false, nullptr, AZ::ConsoleFunctorFlags::Null,
+ bool, ed_useNewAssetBrowserTableView, true, nullptr, AZ::ConsoleFunctorFlags::Null,
"Use the new AssetBrowser TableView for searching assets.");
namespace AzToolsFramework
{
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Thumbnails/SourceThumbnail.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Thumbnails/SourceThumbnail.cpp
index a5206c9608..4869e0d09f 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Thumbnails/SourceThumbnail.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Thumbnails/SourceThumbnail.cpp
@@ -9,11 +9,11 @@
#include
#include
#include
+#include
#include
#include
#include
#include
-#include
#include
namespace AzToolsFramework
@@ -113,11 +113,9 @@ namespace AzToolsFramework
if (iconPathToUse.isEmpty())
{
- const char* engineRoot = nullptr;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
- AZ_Assert(engineRoot, "Engine Root not initialized");
- AZStd::string iconPath = AZStd::string::format("%s%s", engineRoot, DefaultFileIconPath);
- iconPathToUse = iconPath.c_str();
+ AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath();
+ AZ_Assert(!engineRoot.empty(), "Engine Root not initialized");
+ iconPathToUse = (engineRoot / DefaultFileIconPath).c_str();
}
m_pixmap.load(iconPathToUse);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp
index 28d6e2bc08..3e256430a2 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp
@@ -15,6 +15,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -468,6 +469,18 @@ namespace AzToolsFramework
EntityIdList children;
EditorEntityInfoRequestBus::EventResult(children, parentId, &EditorEntityInfoRequestBus::Events::GetChildren);
+ // If Prefabs are enabled, don't check the order for an invalid parent, just return its children (i.e. the root container entity)
+ // There will currently always be one root container entity, so there's no order to retrieve
+ if (!parentId.IsValid())
+ {
+ bool isPrefabEnabled = false;
+ AzFramework::ApplicationRequests::Bus::BroadcastResult(isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
+ if (isPrefabEnabled)
+ {
+ return children;
+ }
+ }
+
EntityIdList entityChildOrder;
AZ::EntityId sortEntityId = GetEntityIdForSortInfo(parentId);
EditorEntitySortRequestBus::EventResult(entityChildOrder, sortEntityId, &EditorEntitySortRequestBus::Events::GetChildEntityOrderArray);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntitySortComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntitySortComponent.cpp
index b747469f4d..6936397187 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntitySortComponent.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntitySortComponent.cpp
@@ -11,6 +11,8 @@
#include
#include
#include
+#include
+#include
static_assert(sizeof(AZ::u64) == sizeof(AZ::EntityId), "We use AZ::EntityId for Persistent ID, which is a u64 under the hood. These must be the same size otherwise the persistent id will have to be rewritten");
@@ -144,6 +146,12 @@ namespace AzToolsFramework
bool EditorEntitySortComponent::AddChildEntityInternal(const AZ::EntityId& entityId, bool addToBack, EntityOrderArray::iterator insertPosition)
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
+
+ if (m_ignoreIncomingOrderChanges)
+ {
+ return true;
+ }
+
auto entityItr = m_childEntityOrderCache.find(entityId);
if (entityItr == m_childEntityOrderCache.end())
{
@@ -198,6 +206,12 @@ namespace AzToolsFramework
bool EditorEntitySortComponent::RemoveChildEntity(const AZ::EntityId& entityId)
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
+
+ if (m_ignoreIncomingOrderChanges)
+ {
+ return true;
+ }
+
auto entityItr = m_childEntityOrderCache.find(entityId);
if (entityItr != m_childEntityOrderCache.end())
{
@@ -250,11 +264,30 @@ namespace AzToolsFramework
}
}
+ void EditorEntitySortComponent::OnPrefabInstancePropagationBegin()
+ {
+ m_ignoreIncomingOrderChanges = true;
+ }
+
+ void EditorEntitySortComponent::OnPrefabInstancePropagationEnd()
+ {
+ m_ignoreIncomingOrderChanges = false;
+ }
+
void EditorEntitySortComponent::MarkDirtyAndSendChangedEvent()
{
// mark the order as dirty before sending the ChildEntityOrderArrayUpdated event in order for PrepareSave to be properly handled in the case
// one of the event listeners needs to build the InstanceDataHierarchy
m_entityOrderIsDirty = true;
+
+ // Force an immediate update for prefabs, which won't receive PrepareSave
+ bool isPrefabEnabled = false;
+ AzFramework::ApplicationRequests::Bus::BroadcastResult(
+ isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
+ if (isPrefabEnabled)
+ {
+ PrepareSave();
+ }
EditorEntitySortNotificationBus::Event(GetEntityId(), &EditorEntitySortNotificationBus::Events::ChildEntityOrderArrayUpdated);
}
@@ -264,10 +297,20 @@ namespace AzToolsFramework
// This is a special case for certain EditorComponents only!
EditorEntitySortRequestBus::Handler::BusConnect(GetEntityId());
EditorEntityContextNotificationBus::Handler::BusConnect();
+ AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusConnect();
}
void EditorEntitySortComponent::Activate()
{
+ // Run the post-serialize handler if prefabs are enabled because PostLoad won't be called automatically
+ bool isPrefabEnabled = false;
+ AzFramework::ApplicationRequests::Bus::BroadcastResult(
+ isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
+ if (isPrefabEnabled)
+ {
+ PostLoad();
+ }
+
// Send out that the order for our entity is now updated
EditorEntitySortNotificationBus::Event(GetEntityId(), &EditorEntitySortNotificationBus::Events::ChildEntityOrderArrayUpdated);
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntitySortComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntitySortComponent.h
index d728191c64..806e903c96 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntitySortComponent.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntitySortComponent.h
@@ -10,6 +10,7 @@
#include "EditorEntitySortBus.h"
#include
#include
+#include
#include
namespace AzToolsFramework
@@ -20,6 +21,7 @@ namespace AzToolsFramework
: public AzToolsFramework::Components::EditorComponentBase
, public EditorEntitySortRequestBus::Handler
, public EditorEntityContextNotificationBus::Handler
+ , public AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler
{
public:
AZ_COMPONENT(EditorEntitySortComponent, "{6EA1E03D-68B2-466D-97F7-83998C8C27F0}", EditorComponentBase);
@@ -45,6 +47,9 @@ namespace AzToolsFramework
// EditorEntityContextNotificationBus::Handler
void OnEntityStreamLoadSuccess() override;
//////////////////////////////////////////////////////////////////////////
+
+ void OnPrefabInstancePropagationBegin() override;
+ void OnPrefabInstancePropagationEnd() override;
private:
void MarkDirtyAndSendChangedEvent();
bool AddChildEntityInternal(const AZ::EntityId& entityId, bool addToBack, EntityOrderArray::iterator insertPosition);
@@ -106,6 +111,7 @@ namespace AzToolsFramework
EntityOrderCache m_childEntityOrderCache; ///< The map of entity id to index for quick look up
bool m_entityOrderIsDirty = true; ///< This flag indicates our stored serialization order data is out of date and must be rebuilt before serialization occurs
+ bool m_ignoreIncomingOrderChanges = false; ///< This is set when prefab propagation occurs so that non-authored order changes can be ignored
};
}
} // namespace AzToolsFramework
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp
index 8098727177..5b51944a75 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp
@@ -175,20 +175,14 @@ namespace AzToolsFramework::Prefab
m_focusedInstance = focusedInstance;
m_focusedTemplateId = focusedInstance->get().GetTemplateId();
- AZ::EntityId containerEntityId;
-
- if (focusedInstance->get().GetParentInstance() != AZStd::nullopt)
- {
- containerEntityId = focusedInstance->get().GetContainerEntityId();
- }
- else
- {
- containerEntityId = AZ::EntityId();
- }
-
// Focus on the descendants of the container entity in the Editor, if the interface is initialized.
if (m_focusModeInterface)
{
+ const AZ::EntityId containerEntityId =
+ (focusedInstance->get().GetParentInstance() != AZStd::nullopt)
+ ? focusedInstance->get().GetContainerEntityId()
+ : AZ::EntityId();
+
m_focusModeInterface->SetFocusRoot(containerEntityId);
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
index 4d826d9700..850b793513 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
@@ -1144,6 +1144,10 @@ namespace AzToolsFramework
AZ::EntityId firstEntityIdToDelete = entityIdsNoFocusContainer[0];
InstanceOptionalReference commonOwningInstance = GetOwnerInstanceByEntityId(firstEntityIdToDelete);
+ if (!commonOwningInstance.has_value())
+ {
+ return AZ::Failure(AZStd::string("Cannot delete entities belonging to an invalid instance"));
+ }
// If the first entity id is a container entity id, then we need to mark its parent as the common owning instance because you
// cannot delete an instance from itself.
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/SourceControlThumbnail.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/SourceControlThumbnail.cpp
index 655fd27a0f..c2636d6d52 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/SourceControlThumbnail.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/SourceControlThumbnail.cpp
@@ -6,10 +6,10 @@
*
*/
-#include
+#include
+#include
#include
#include
-#include
namespace AzToolsFramework
{
@@ -68,12 +68,12 @@ namespace AzToolsFramework
SourceControlThumbnail::SourceControlThumbnail(SharedThumbnailKey key)
: Thumbnail(key)
{
- const char* engineRoot = nullptr;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
- AZ_Assert(engineRoot, "Engine Root not initialized");
+ AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath();
+ AZ_Assert(!engineRoot.empty(), "Engine Root not initialized");
+
+ m_writableIconPath = (engineRoot / WRITABLE_ICON_PATH).String();
+ m_nonWritableIconPath = (engineRoot / NONWRITABLE_ICON_PATH).String();
- AzFramework::StringFunc::Path::Join(engineRoot, WRITABLE_ICON_PATH, m_writableIconPath);
- AzFramework::StringFunc::Path::Join(engineRoot, NONWRITABLE_ICON_PATH, m_nonWritableIconPath);
BusConnect();
}
@@ -90,8 +90,8 @@ namespace AzToolsFramework
AZ_Assert(sourceControlKey, "Incorrect key type, excpected SourceControlThumbnailKey");
AZStd::string myFileName(sourceControlKey->GetFileName());
- AzFramework::StringFunc::Path::Normalize(myFileName);
- if (AzFramework::StringFunc::Equal(myFileName.c_str(), filename))
+ AZ::StringFunc::Path::Normalize(myFileName);
+ if (AZ::StringFunc::Equal(myFileName.c_str(), filename))
{
Update();
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp
index 9ffe8021e3..29bc106eed 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp
@@ -45,6 +45,7 @@ AZ_POP_DISABLE_WARNING
#include
#include
#include
+#include
#include
#include
#include
@@ -606,6 +607,7 @@ namespace AzToolsFramework
AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
AzToolsFramework::GetEntityContextId());
+ ViewportEditorModeNotificationsBus::Handler::BusConnect(GetEntityContextId());
}
EntityPropertyEditor::~EntityPropertyEditor()
@@ -618,7 +620,8 @@ namespace AzToolsFramework
AZ::EntitySystemBus::Handler::BusDisconnect();
EditorEntityContextNotificationBus::Handler::BusDisconnect();
AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
-
+ ViewportEditorModeNotificationsBus::Handler::BusDisconnect();
+
for (auto& entityId : m_overrideSelectedEntityIds)
{
DisconnectFromEntityBuses(entityId);
@@ -892,25 +895,51 @@ namespace AzToolsFramework
{
if (!m_prefabsAreEnabled)
{
- return m_isLevelEntityEditor ? InspectorLayout::LEVEL : InspectorLayout::ENTITY;
+ return m_isLevelEntityEditor ? InspectorLayout::Level : InspectorLayout::Entity;
}
+ // Prefabs layout logic
+
+ // If this is the container entity for the root instance, treat it like a level entity.
AZ::EntityId levelContainerEntityId = m_prefabPublicInterface->GetLevelInstanceContainerEntityId();
if (AZStd::find(m_selectedEntityIds.begin(), m_selectedEntityIds.end(), levelContainerEntityId) != m_selectedEntityIds.end())
{
if (m_selectedEntityIds.size() > 1)
{
- return InspectorLayout::INVALID;
+ return InspectorLayout::Invalid;
}
else
{
- return InspectorLayout::LEVEL;
+ return InspectorLayout::Level;
}
}
else
{
- return InspectorLayout::ENTITY;
+ // If this is the container entity for the currently focused prefab, utilize a separate layout.
+ if (auto prefabFocusPublicInterface = AZ::Interface::Get())
+ {
+ AzFramework::EntityContextId editorEntityContextId = AzFramework::EntityContextId::CreateNull();
+ EditorEntityContextRequestBus::BroadcastResult(
+ editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
+
+ AZ::EntityId focusedPrefabContainerEntityId =
+ prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId);
+ if (AZStd::find(m_selectedEntityIds.begin(), m_selectedEntityIds.end(), focusedPrefabContainerEntityId) !=
+ m_selectedEntityIds.end())
+ {
+ if (m_selectedEntityIds.size() > 1)
+ {
+ return InspectorLayout::Invalid;
+ }
+ else
+ {
+ return InspectorLayout::ContainerEntityOfFocusedPrefab;
+ }
+ }
+ }
}
+
+ return InspectorLayout::Entity;
}
void EntityPropertyEditor::UpdateEntityDisplay()
@@ -919,7 +948,7 @@ namespace AzToolsFramework
InspectorLayout layout = GetCurrentInspectorLayout();
- if (layout == InspectorLayout::LEVEL)
+ if (!m_prefabsAreEnabled && layout == InspectorLayout::Level)
{
AZStd::string levelName;
AzToolsFramework::EditorRequestBus::BroadcastResult(levelName, &AzToolsFramework::EditorRequests::GetLevelName);
@@ -961,14 +990,19 @@ namespace AzToolsFramework
InspectorLayout layout = GetCurrentInspectorLayout();
- if (layout == InspectorLayout::LEVEL)
+ if (layout == InspectorLayout::Level)
{
// The Level Inspector should only have a list of selectable components after the
// level entity itself is valid (i.e. "selected").
return selection.empty() ? SelectionEntityTypeInfo::None : SelectionEntityTypeInfo::LevelEntity;
}
- if (layout == InspectorLayout::INVALID)
+ if (layout == InspectorLayout::ContainerEntityOfFocusedPrefab)
+ {
+ return selection.empty() ? SelectionEntityTypeInfo::None : SelectionEntityTypeInfo::ContainerEntityOfFocusedPrefab;
+ }
+
+ if (layout == InspectorLayout::Invalid)
{
return SelectionEntityTypeInfo::Mixed;
}
@@ -1138,7 +1172,8 @@ namespace AzToolsFramework
}
}
- bool isLevelLayout = GetCurrentInspectorLayout() == InspectorLayout::LEVEL;
+ bool isLevelLayout = GetCurrentInspectorLayout() == InspectorLayout::Level;
+ bool isContainerOfFocusedPrefabLayout = GetCurrentInspectorLayout() == InspectorLayout::ContainerEntityOfFocusedPrefab;
m_gui->m_entityDetailsLabel->setText(entityDetailsLabelText);
m_gui->m_entityDetailsLabel->setVisible(entityDetailsVisible);
@@ -1146,10 +1181,14 @@ namespace AzToolsFramework
m_gui->m_entityNameLabel->setVisible(hasEntitiesDisplayed);
m_gui->m_entityIcon->setVisible(hasEntitiesDisplayed);
m_gui->m_pinButton->setVisible(m_overrideSelectedEntityIds.empty() && hasEntitiesDisplayed && !m_isSystemEntityEditor);
- m_gui->m_statusLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
- m_gui->m_statusComboBox->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
- m_gui->m_entityIdLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
- m_gui->m_entityIdText->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
+ m_gui->m_statusLabel->setVisible(
+ hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
+ m_gui->m_statusComboBox->setVisible(
+ hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
+ m_gui->m_entityIdLabel->setVisible(
+ hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
+ m_gui->m_entityIdText->setVisible(
+ hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
bool displayComponentSearchBox = hasEntitiesDisplayed;
if (hasEntitiesDisplayed)
@@ -1157,7 +1196,9 @@ namespace AzToolsFramework
// Build up components to display
SharedComponentArray sharedComponentArray;
BuildSharedComponentArray(sharedComponentArray,
- !(selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyStandardEntities || selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyPrefabEntities));
+ !(selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyStandardEntities ||
+ selectionEntityTypeInfo == SelectionEntityTypeInfo::OnlyPrefabEntities) ||
+ selectionEntityTypeInfo == SelectionEntityTypeInfo::ContainerEntityOfFocusedPrefab);
if (sharedComponentArray.size() == 0)
{
@@ -1173,7 +1214,8 @@ namespace AzToolsFramework
UpdateEntityDisplay();
}
- m_gui->m_darkBox->setVisible(displayComponentSearchBox && !m_isSystemEntityEditor && !isLevelLayout);
+ m_gui->m_darkBox->setVisible(
+ displayComponentSearchBox && !m_isSystemEntityEditor && !isLevelLayout && !isContainerOfFocusedPrefabLayout);
m_gui->m_entitySearchBox->setVisible(displayComponentSearchBox);
bool displayAddComponentMenu = CanAddComponentsToSelection(selectionEntityTypeInfo);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx
index 5279cefa9f..8dd0ffc4ee 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx
@@ -354,7 +354,8 @@ namespace AzToolsFramework
OnlyLayerEntities,
OnlyPrefabEntities,
Mixed,
- LevelEntity
+ LevelEntity,
+ ContainerEntityOfFocusedPrefab
};
/**
* Returns what kinds of entities are in the current selection. This is used because mixed selection
@@ -364,7 +365,7 @@ namespace AzToolsFramework
SelectionEntityTypeInfo GetSelectionEntityTypeInfo(const EntityIdList& selection) const;
/**
- * Returns true if a selection matching the passed in selection informatation allows components to be added.
+ * Returns true if a selection matching the passed in selection information allows components to be added.
*/
bool CanAddComponentsToSelection(const SelectionEntityTypeInfo& selectionEntityTypeInfo) const;
@@ -581,9 +582,10 @@ namespace AzToolsFramework
enum class InspectorLayout
{
- ENTITY = 0, // All selected entities are regular entities
- LEVEL, // The selected entity is the level prefab container entity
- INVALID // Other entities are selected alongside the level prefab container entity
+ Entity = 0, // All selected entities are regular entities.
+ Level, // The selected entity is the prefab container entity for the level prefab, or the slice level entity.
+ ContainerEntityOfFocusedPrefab, // The selected entity is the prefab container entity for the focused prefab.
+ Invalid // Other entities are selected alongside the level prefab container entity.
};
InspectorLayout GetCurrentInspectorLayout() const;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp
index 39c882b766..c16a458be7 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp
@@ -28,6 +28,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -1177,8 +1178,10 @@ namespace AzToolsFramework
continue;
}
- const AZ::Aabb bound = CalculateEditorEntitySelectionBounds(entityId, viewportInfo);
- debugDisplay.DrawSolidBox(bound.GetMin(), bound.GetMax());
+ if (const AZ::Aabb bound = CalculateEditorEntitySelectionBounds(entityId, viewportInfo); bound.IsValid())
+ {
+ debugDisplay.DrawSolidBox(bound.GetMin(), bound.GetMax());
+ }
}
debugDisplay.DepthTestOn();
@@ -1334,39 +1337,6 @@ namespace AzToolsFramework
EndRecordManipulatorCommand();
});
- // surface
- translationManipulators->InstallSurfaceManipulatorMouseDownCallback(
- [this, manipulatorEntityIds]([[maybe_unused]] const SurfaceManipulator::Action& action)
- {
- BuildSortedEntityIdVectorFromEntityIdMap(m_entityIdManipulators.m_lookups, manipulatorEntityIds->m_entityIds);
-
- InitializeTranslationLookup(m_entityIdManipulators);
-
- m_axisPreview.m_translation = m_entityIdManipulators.m_manipulators->GetLocalTransform().GetTranslation();
- m_axisPreview.m_orientation = QuaternionFromTransformNoScaling(m_entityIdManipulators.m_manipulators->GetLocalTransform());
-
- // [ref 1.]
- BeginRecordManipulatorCommand();
- });
-
- translationManipulators->InstallSurfaceManipulatorMouseMoveCallback(
- [this, prevModifiers, manipulatorEntityIds](const SurfaceManipulator::Action& action) mutable
- {
- UpdateTranslationManipulator(
- action, manipulatorEntityIds->m_entityIds, m_entityIdManipulators, m_pivotOverrideFrame, prevModifiers,
- m_transformChangedInternally, m_spaceCluster.m_spaceLock);
- });
-
- translationManipulators->InstallSurfaceManipulatorMouseUpCallback(
- [this, manipulatorEntityIds]([[maybe_unused]] const SurfaceManipulator::Action& action)
- {
- AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast(
- &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanged,
- manipulatorEntityIds->m_entityIds);
-
- EndRecordManipulatorCommand();
- });
-
// transfer ownership
m_entityIdManipulators.m_manipulators = AZStd::move(translationManipulators);
}
@@ -3604,6 +3574,16 @@ namespace AzToolsFramework
m_selectedEntityIds.clear();
m_selectedEntityIds.reserve(selectedEntityIds.size());
AZStd::copy(selectedEntityIds.begin(), selectedEntityIds.end(), AZStd::inserter(m_selectedEntityIds, m_selectedEntityIds.end()));
+
+ // Do not create manipulators for the container entity of the focused prefab.
+ if (auto prefabFocusPublicInterface = AZ::Interface::Get())
+ {
+ AzFramework::EntityContextId editorEntityContextId = GetEntityContextId();
+ if (AZ::EntityId focusRoot = prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId); focusRoot.IsValid())
+ {
+ m_selectedEntityIds.erase(focusRoot);
+ }
+ }
}
void EditorTransformComponentSelection::OnTransformChanged(
diff --git a/Code/Framework/AzToolsFramework/Tests/ComponentAddRemove.cpp b/Code/Framework/AzToolsFramework/Tests/ComponentAddRemove.cpp
index 9d6c8a4bff..06353b17c5 100644
--- a/Code/Framework/AzToolsFramework/Tests/ComponentAddRemove.cpp
+++ b/Code/Framework/AzToolsFramework/Tests/ComponentAddRemove.cpp
@@ -1116,7 +1116,6 @@ namespace UnitTest
SerializeContext* GetSerializeContext() override { return m_serializeContext.get(); }
BehaviorContext* GetBehaviorContext() override { return nullptr; }
JsonRegistrationContext* GetJsonRegistrationContext() override { return nullptr; }
- const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
diff --git a/Code/Framework/AzToolsFramework/Tests/UI/EntityPropertyEditorTests.cpp b/Code/Framework/AzToolsFramework/Tests/UI/EntityPropertyEditorTests.cpp
index c24bab9299..a3c6666a40 100644
--- a/Code/Framework/AzToolsFramework/Tests/UI/EntityPropertyEditorTests.cpp
+++ b/Code/Framework/AzToolsFramework/Tests/UI/EntityPropertyEditorTests.cpp
@@ -36,11 +36,6 @@ namespace UnitTest
: public ComponentApplication
{
public:
- void SetExecutableFolder(const char* path)
- {
- m_exeDirectory = path;
- }
-
void SetSettingsRegistrySpecializations(SettingsRegistryInterface::Specializations& specializations) override
{
ComponentApplication::SetSettingsRegistrySpecializations(specializations);
diff --git a/Code/LauncherUnified/Launcher.cpp b/Code/LauncherUnified/Launcher.cpp
index c37f70c3b7..1a87626e35 100644
--- a/Code/LauncherUnified/Launcher.cpp
+++ b/Code/LauncherUnified/Launcher.cpp
@@ -228,7 +228,6 @@ namespace O3DELauncher
}
}
- void CompileCriticalAssets();
void CreateRemoteFileIO();
bool ConnectToAssetProcessor()
@@ -256,29 +255,11 @@ namespace O3DELauncher
{
AZ_TracePrintf("Launcher", "Connected to Asset Processor\n");
CreateRemoteFileIO();
- CompileCriticalAssets();
}
return connectedToAssetProcessor;
}
- //! Compiles the critical assets that are within the Engine directory of Open 3D Engine
- //! This code should be in a centralized location, but doesn't belong in AzFramework
- //! since it is specific to how Open 3D Engine projects has assets setup
- void CompileCriticalAssets()
- {
- // VERY early on, as soon as we can, request that the asset system make sure the following assets take priority over others,
- // so that by the time we ask for them there is a greater likelihood that they're already good to go.
- // these can be loaded later but are still important:
- AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "/texturemsg/");
- AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/materials");
- AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/geomcaches");
- AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, "engineassets/objects");
-
- // some are specifically extra important and will cause issues if missing completely:
- AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::CompileAssetSync, "engineassets/objects/default.cgf");
- }
-
//! Remote FileIO to use as a Virtual File System
//! Communication of FileIOBase operations occur through an AssetProcessor connection
void CreateRemoteFileIO()
diff --git a/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.cpp b/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.cpp
index b17832526f..17e621f7d6 100644
--- a/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.cpp
+++ b/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.cpp
@@ -346,9 +346,7 @@ namespace AssetBundler
}
// Determine the enabled platforms
- const char* appRoot = nullptr;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(appRoot, &AzFramework::ApplicationRequests::GetAppRoot);
- m_enabledPlatforms = GetEnabledPlatformFlags(GetEngineRoot(), appRoot, AZ::Utils::GetProjectPath().c_str());
+ m_enabledPlatforms = GetEnabledPlatformFlags(GetEngineRoot(), AZStd::string_view(AZ::Utils::GetProjectPath()));
// Determine which Gems are enabled for the current project
if (!AzFramework::GetGemsInfo(m_gemInfoList, *m_settingsRegistry))
diff --git a/Code/Tools/AssetBundler/source/utils/applicationManager.cpp b/Code/Tools/AssetBundler/source/utils/applicationManager.cpp
index 0388570fdd..2df9e64ac5 100644
--- a/Code/Tools/AssetBundler/source/utils/applicationManager.cpp
+++ b/Code/Tools/AssetBundler/source/utils/applicationManager.cpp
@@ -1401,7 +1401,6 @@ namespace AssetBundler
// If no platform was specified, defaulting to platforms specified in the asset processor config files
AzFramework::PlatformFlags platformFlags = GetEnabledPlatformFlags(
- AZStd::string_view{ AZ::Utils::GetEnginePath() },
AZStd::string_view{ AZ::Utils::GetEnginePath() },
AZStd::string_view{ AZ::Utils::GetProjectPath() });
[[maybe_unused]] auto platformsString = AzFramework::PlatformHelper::GetCommaSeparatedPlatformList(platformFlags);
diff --git a/Code/Tools/AssetBundler/source/utils/utils.cpp b/Code/Tools/AssetBundler/source/utils/utils.cpp
index 6daf3c571b..7e56f5450e 100644
--- a/Code/Tools/AssetBundler/source/utils/utils.cpp
+++ b/Code/Tools/AssetBundler/source/utils/utils.cpp
@@ -377,7 +377,6 @@ namespace AssetBundler
AzFramework::PlatformFlags GetEnabledPlatformFlags(
AZStd::string_view engineRoot,
- AZStd::string_view assetRoot,
AZStd::string_view projectPath)
{
auto settingsRegistry = AZ::SettingsRegistry::Get();
@@ -387,7 +386,7 @@ namespace AssetBundler
return AzFramework::PlatformFlags::Platform_NONE;
}
- auto configFiles = AzToolsFramework::AssetUtils::GetConfigFiles(engineRoot, assetRoot, projectPath, true, true, settingsRegistry);
+ auto configFiles = AzToolsFramework::AssetUtils::GetConfigFiles(engineRoot, projectPath, true, true, settingsRegistry);
auto enabledPlatformList = AzToolsFramework::AssetUtils::GetEnabledPlatforms(*settingsRegistry, configFiles);
AzFramework::PlatformFlags platformFlags = AzFramework::PlatformFlags::Platform_NONE;
for (const auto& enabledPlatform : enabledPlatformList)
diff --git a/Code/Tools/AssetBundler/source/utils/utils.h b/Code/Tools/AssetBundler/source/utils/utils.h
index bfdf252014..0986d70ca8 100644
--- a/Code/Tools/AssetBundler/source/utils/utils.h
+++ b/Code/Tools/AssetBundler/source/utils/utils.h
@@ -221,7 +221,6 @@ namespace AssetBundler
//! Please note that the game project could be in a different location to the engine therefore we need the assetRoot param.
AzFramework::PlatformFlags GetEnabledPlatformFlags(
AZStd::string_view enginePath,
- AZStd::string_view assetRoot,
AZStd::string_view projectPath);
QJsonObject ReadJson(const AZStd::string& filePath);
diff --git a/Code/Tools/AssetBundler/tests/UtilsTests.cpp b/Code/Tools/AssetBundler/tests/UtilsTests.cpp
index 560d399613..60fc79579b 100644
--- a/Code/Tools/AssetBundler/tests/UtilsTests.cpp
+++ b/Code/Tools/AssetBundler/tests/UtilsTests.cpp
@@ -67,7 +67,7 @@ namespace AssetBundler
void NormalizePathKeepCase(AZStd::string& /*path*/) override {}
void CalculateBranchTokenForEngineRoot(AZStd::string& /*token*/) const override {}
- const char* GetEngineRoot() const override
+ const char* GetTempDir() const
{
return m_tempDir->GetDirectory();
}
@@ -83,7 +83,7 @@ namespace AssetBundler
TEST_F(MockUtilsTest, DISABLED_TestFilePath_StartsWithAFileSeparator_Valid)
{
AZ::IO::Path relFilePath = "Foo/foo.xml";
- AZ::IO::Path absoluteFilePath = AZ::IO::PathView(GetEngineRoot()).RootPath();
+ AZ::IO::Path absoluteFilePath = AZ::IO::PathView(GetTempDir()).RootPath();
absoluteFilePath /= relFilePath;
absoluteFilePath = absoluteFilePath.LexicallyNormal();
@@ -95,7 +95,7 @@ namespace AssetBundler
TEST_F(MockUtilsTest, TestFilePath_RelativePath_Valid)
{
AZ::IO::Path relFilePath = "Foo\\foo.xml";
- AZ::IO::Path absoluteFilePath = (AZ::IO::Path(GetEngineRoot()) / relFilePath).LexicallyNormal();
+ AZ::IO::Path absoluteFilePath = (AZ::IO::Path(GetTempDir()) / relFilePath).LexicallyNormal();
FilePath filePath(relFilePath.Native());
EXPECT_EQ(AZ::IO::PathView{ filePath.AbsolutePath() }, absoluteFilePath);
}
@@ -107,8 +107,8 @@ namespace AssetBundler
AZ::IO::Path relFilePath = "Foo\\Foo.xml";
AZ::IO::Path wrongCaseRelFilePath = "Foo\\foo.xml";
- AZ::IO::Path correctAbsoluteFilePath = (AZ::IO::Path(GetEngineRoot()) / relFilePath).LexicallyNormal();
- AZ::IO::Path wrongCaseAbsoluteFilePath = (AZ::IO::Path(GetEngineRoot()) / wrongCaseRelFilePath).LexicallyNormal();
+ AZ::IO::Path correctAbsoluteFilePath = (AZ::IO::Path(GetTempDir()) / relFilePath).LexicallyNormal();
+ AZ::IO::Path wrongCaseAbsoluteFilePath = (AZ::IO::Path(GetTempDir()) / wrongCaseRelFilePath).LexicallyNormal();
AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
AZ::IO::FileIOBase::GetInstance()->Open(correctAbsoluteFilePath.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeCreatePath, fileHandle);
@@ -121,7 +121,7 @@ namespace AssetBundler
TEST_F(MockUtilsTest, TestFilePath_NoFileExists_NoError_valid)
{
AZ::IO::Path relFilePath = "Foo\\Foo.xml";
- AZ::IO::Path absoluteFilePath = (AZ::IO::Path(GetEngineRoot()) / relFilePath).LexicallyNormal();
+ AZ::IO::Path absoluteFilePath = (AZ::IO::Path(GetTempDir()) / relFilePath).LexicallyNormal();
FilePath filePath(absoluteFilePath.Native(), true, false);
EXPECT_TRUE(filePath.IsValid());
@@ -132,8 +132,8 @@ namespace AssetBundler
{
AZStd::string relFilePath = "Foo\\Foo.xml";
AZStd::string wrongCaseRelFilePath = "Foo\\foo.xml";
- AZ::IO::Path correctAbsoluteFilePath = (AZ::IO::Path(GetEngineRoot()) / relFilePath).LexicallyNormal();
- AZ::IO::Path wrongCaseAbsoluteFilePath = (AZ::IO::Path(GetEngineRoot()) / wrongCaseRelFilePath).LexicallyNormal();
+ AZ::IO::Path correctAbsoluteFilePath = (AZ::IO::Path(GetTempDir()) / relFilePath).LexicallyNormal();
+ AZ::IO::Path wrongCaseAbsoluteFilePath = (AZ::IO::Path(GetTempDir()) / wrongCaseRelFilePath).LexicallyNormal();
AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
AZ::IO::FileIOBase::GetInstance()->Open(correctAbsoluteFilePath.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeCreatePath, fileHandle);
diff --git a/Code/Tools/AssetBundler/tests/applicationManagerTests.cpp b/Code/Tools/AssetBundler/tests/applicationManagerTests.cpp
index 07eae67a81..fd587195af 100644
--- a/Code/Tools/AssetBundler/tests/applicationManagerTests.cpp
+++ b/Code/Tools/AssetBundler/tests/applicationManagerTests.cpp
@@ -16,6 +16,7 @@
#include
#include
#include
+#include
#include
#include
@@ -84,10 +85,9 @@ namespace AssetBundler
// in the unit tests.
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
- const char* engineRoot = nullptr;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
- ASSERT_TRUE(engineRoot) << "Unable to locate engine root.\n";
- AzFramework::StringFunc::Path::Join(engineRoot, RelativeTestFolder, m_data->m_testEngineRoot);
+ AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath();
+ ASSERT_TRUE(!engineRoot.empty()) << "Unable to locate engine root.\n";
+ m_data->m_testEngineRoot = (engineRoot / RelativeTestFolder).String();
m_data->m_localFileIO = aznew AZ::IO::LocalFileIO();
m_data->m_priorFileIO = AZ::IO::FileIOBase::GetInstance();
@@ -150,7 +150,8 @@ namespace AssetBundler
EXPECT_EQ(0, gemsNameMap.size());
- AzFramework::PlatformFlags platformFlags = GetEnabledPlatformFlags(m_data->m_testEngineRoot.c_str(), m_data->m_testEngineRoot.c_str(), DummyProjectName);
+ const auto testProjectPath = AZ::IO::Path(m_data->m_testEngineRoot) / DummyProjectName;
+ AzFramework::PlatformFlags platformFlags = GetEnabledPlatformFlags(m_data->m_testEngineRoot, testProjectPath.Native());
AzFramework::PlatformFlags hostPlatformFlag = AzFramework::PlatformHelper::GetPlatformFlag(AzToolsFramework::AssetSystem::GetHostAssetPlatform());
AzFramework::PlatformFlags expectedFlags = AzFramework::PlatformFlags::Platform_ANDROID | AzFramework::PlatformFlags::Platform_IOS | AzFramework::PlatformFlags::Platform_PROVO | hostPlatformFlag;
ASSERT_EQ(platformFlags, expectedFlags);
diff --git a/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp b/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp
index 62b063c83b..a02eef8b75 100644
--- a/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp
+++ b/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp
@@ -699,7 +699,6 @@ namespace AssetBuilderSDK
// XML files may contain generic data (avoid this in new builders - use a custom extension!)
static const char* xmlExtensions = ".xml";
- static const char* geomCacheExtensions = ".cax";
static const char* skeletonExtensions = ".chr";
static AZ::Data::AssetType unknownAssetType = AZ::Data::AssetType::CreateNull();
@@ -710,7 +709,6 @@ namespace AssetBuilderSDK
static AZ::Data::AssetType textureMipsAssetType("{3918728C-D3CA-4D9E-813E-A5ED20C6821E}");
static AZ::Data::AssetType skinnedMeshLodsAssetType("{58E5824F-C27B-46FD-AD48-865BA41B7A51}");
static AZ::Data::AssetType staticMeshLodsAssetType("{9AAE4926-CB6A-4C60-9948-A1A22F51DB23}");
- static AZ::Data::AssetType geomCacheAssetType("{EBC96071-E960-41B6-B3E3-328F515AE5DA}");
static AZ::Data::AssetType skeletonAssetType("{60161B46-21F0-4396-A4F0-F2CCF0664CDE}");
static AZ::Data::AssetType entityIconAssetType("{3436C30E-E2C5-4C3B-A7B9-66C94A28701B}");
@@ -822,11 +820,6 @@ namespace AssetBuilderSDK
return skinnedMeshAssetType;
}
- if (AzFramework::StringFunc::Find(geomCacheExtensions, extension.c_str()) != AZStd::string::npos)
- {
- return geomCacheAssetType;
- }
-
if (AzFramework::StringFunc::Find(skeletonExtensions, extension.c_str()) != AZStd::string::npos)
{
return skeletonAssetType;
diff --git a/Code/Tools/AssetProcessor/native/tests/platformconfiguration/platformconfigurationtests.cpp b/Code/Tools/AssetProcessor/native/tests/platformconfiguration/platformconfigurationtests.cpp
index 6fd05fa948..624fa3d06b 100644
--- a/Code/Tools/AssetProcessor/native/tests/platformconfiguration/platformconfigurationtests.cpp
+++ b/Code/Tools/AssetProcessor/native/tests/platformconfiguration/platformconfigurationtests.cpp
@@ -52,11 +52,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_BadPlatform)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
+ const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_badplatform");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
- ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
+ ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
}
@@ -67,11 +68,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_NoPlatform)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
+ const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_noplatform");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
- ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
+ ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
}
@@ -81,11 +83,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_NoScanFolders)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
+ const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_noscans");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
- ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
+ ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
}
@@ -95,11 +98,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_BrokenRecognizers)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
+ const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_broken_recognizers");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
- ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
+ ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
}
@@ -109,11 +113,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Regular_Platforms)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
+ const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
- ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
+ ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
// verify the data.
@@ -322,12 +327,13 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolder)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
+ const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
AssetUtilities::ComputeProjectName(EmptyDummyProjectName, true);
- ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
+ ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
ASSERT_EQ(config.GetScanFolderCount(), 3); // the two, and then the one that has the same data as prior but different identifier.
@@ -356,11 +362,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolderP
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
+ const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular_platform_scanfolder");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
- ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
+ ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
ASSERT_EQ(config.GetScanFolderCount(), 5);
@@ -402,13 +409,14 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularExcludes)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
+ const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
config.AddScanFolder(ScanFolderInfo("blahblah", "Blah ScanFolder", "sf2", true, true), true);
m_absorber.Clear();
- ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
+ ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
ASSERT_TRUE(config.IsFileExcluded("blahblah/$tmp_01.test"));
@@ -429,11 +437,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Recognizers)
#endif
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
+ const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
- ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
+ ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
const AssetProcessor::RecognizerContainer& recogs = config.GetAssetRecognizerContainer();
@@ -520,12 +529,13 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Overrides)
using namespace AzToolsFramework::AssetSystem;
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
+ const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / DummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
- ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), DummyProjectName, false, false));
+ ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
const AssetProcessor::RecognizerContainer& recogs = config.GetAssetRecognizerContainer();
@@ -627,11 +637,12 @@ TEST_F(PlatformConfigurationUnitTests, ReadCheckServer_FromConfig_Valid)
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
+ const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_regular");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
- ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
+ ASSERT_TRUE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_EQ(m_absorber.m_numErrorsAbsorbed, 0);
const AssetProcessor::RecognizerContainer& recogs = config.GetAssetRecognizerContainer();
@@ -676,11 +687,12 @@ TEST_F(PlatformConfigurationUnitTests, Test_MetaFileTypes_AssetImporterExtension
using namespace AssetProcessor;
const auto testExeFolder = AZ::IO::FileIOBase::GetInstance()->ResolvePath(TestAppRoot);
+ const AZ::IO::FixedMaxPath projectPath = (*testExeFolder) / EmptyDummyProjectName;
auto configRoot = AZ::IO::FileIOBase::GetInstance()->ResolvePath("@exefolder@/testdata/config_metadata");
ASSERT_TRUE(configRoot);
UnitTestPlatformConfiguration config;
m_absorber.Clear();
- ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), EmptyDummyProjectName, false, false));
+ ASSERT_FALSE(config.InitializeFromConfigFiles(configRoot->c_str(), testExeFolder->c_str(), projectPath.c_str(), false, false));
ASSERT_GT(m_absorber.m_numErrorsAbsorbed, 0);
ASSERT_TRUE(config.MetaDataFileTypesCount() == 2);
diff --git a/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp b/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp
index bcadd0f103..bc516d5da6 100644
--- a/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp
+++ b/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp
@@ -749,7 +749,7 @@ namespace AssetProcessor
}
AZStd::vector configFiles = AzToolsFramework::AssetUtils::GetConfigFiles(absoluteSystemRoot.toUtf8().constData(),
- absoluteAssetRoot.toUtf8().constData(), projectPath.toUtf8().constData(),
+ projectPath.toUtf8().constData(),
addPlatformConfigs, addGemsConfigs && !noGemScanFolders, settingsRegistry);
// First Merge all Engine, Gem and Project specific AssetProcessor*Config.setreg/.inifiles
diff --git a/Code/Tools/ProjectManager/Source/DownloadController.cpp b/Code/Tools/ProjectManager/Source/DownloadController.cpp
index d30e1bbc7c..6326b2fc11 100644
--- a/Code/Tools/ProjectManager/Source/DownloadController.cpp
+++ b/Code/Tools/ProjectManager/Source/DownloadController.cpp
@@ -41,9 +41,11 @@ namespace O3DE::ProjectManager
void DownloadController::AddGemDownload(const QString& gemName)
{
m_gemNames.push_back(gemName);
+ emit GemDownloadAdded(gemName);
+
if (m_gemNames.size() == 1)
{
- m_worker->SetGemToDownload(m_gemNames[0], false);
+ m_worker->SetGemToDownload(m_gemNames.front(), false);
m_workerThread.start();
}
}
@@ -62,6 +64,7 @@ namespace O3DE::ProjectManager
else
{
m_gemNames.erase(findResult);
+ emit GemDownloadRemoved(gemName);
}
}
}
@@ -69,7 +72,7 @@ namespace O3DE::ProjectManager
void DownloadController::UpdateUIProgress(int progress)
{
m_lastProgress = progress;
- emit GemDownloadProgress(progress);
+ emit GemDownloadProgress(m_gemNames.front(), progress);
}
void DownloadController::HandleResults(const QString& result)
diff --git a/Code/Tools/ProjectManager/Source/DownloadController.h b/Code/Tools/ProjectManager/Source/DownloadController.h
index 5b2d230379..0bf0ae473c 100644
--- a/Code/Tools/ProjectManager/Source/DownloadController.h
+++ b/Code/Tools/ProjectManager/Source/DownloadController.h
@@ -59,7 +59,9 @@ namespace O3DE::ProjectManager
signals:
void StartGemDownload(const QString& gemName);
void Done(const QString& gemName, bool success = true);
- void GemDownloadProgress(int percentage);
+ void GemDownloadAdded(const QString& gemName);
+ void GemDownloadRemoved(const QString& gemName);
+ void GemDownloadProgress(const QString& gemName, int percentage);
private:
DownloadWorker* m_worker;
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp
index 8c875e4846..bd0a6e9bc3 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp
@@ -30,6 +30,7 @@ namespace O3DE::ProjectManager
m_layout->setMargin(5);
m_layout->setAlignment(Qt::AlignTop);
setLayout(m_layout);
+ setMinimumHeight(400);
QHBoxLayout* hLayout = new QHBoxLayout();
@@ -119,6 +120,12 @@ namespace O3DE::ProjectManager
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
}
+ CartOverlayWidget::~CartOverlayWidget()
+ {
+ // disconnect from all download controller signals
+ disconnect(m_downloadController, nullptr, this, nullptr);
+ }
+
void CartOverlayWidget::CreateGemSection(const QString& singularTitle, const QString& pluralTitle, GetTagIndicesCallback getTagIndices)
{
QWidget* widget = new QWidget();
@@ -162,13 +169,13 @@ namespace O3DE::ProjectManager
void CartOverlayWidget::CreateDownloadSection()
{
- QWidget* widget = new QWidget();
- widget->setFixedWidth(s_width);
- m_layout->addWidget(widget);
+ m_downloadSectionWidget = new QWidget();
+ m_downloadSectionWidget->setFixedWidth(s_width);
+ m_layout->addWidget(m_downloadSectionWidget);
QVBoxLayout* layout = new QVBoxLayout();
layout->setAlignment(Qt::AlignTop);
- widget->setLayout(layout);
+ m_downloadSectionWidget->setLayout(layout);
QLabel* titleLabel = new QLabel();
titleLabel->setObjectName("GemCatalogCartOverlaySectionLabel");
@@ -187,88 +194,121 @@ namespace O3DE::ProjectManager
QLabel* processingQueueLabel = new QLabel("Processing Queue");
gemDownloadLayout->addWidget(processingQueueLabel);
- QWidget* downloadingItemWidget = new QWidget();
- downloadingItemWidget->setObjectName("GemCatalogCartOverlayGemDownloadBG");
- gemDownloadLayout->addWidget(downloadingItemWidget);
+ m_downloadingListWidget = new QWidget();
+ m_downloadingListWidget->setObjectName("GemCatalogCartOverlayGemDownloadBG");
+ gemDownloadLayout->addWidget(m_downloadingListWidget);
QVBoxLayout* downloadingItemLayout = new QVBoxLayout();
downloadingItemLayout->setAlignment(Qt::AlignTop);
- downloadingItemWidget->setLayout(downloadingItemLayout);
+ m_downloadingListWidget->setLayout(downloadingItemLayout);
- auto update = [=](int downloadProgress)
+ QLabel* downloadsInProgessLabel = new QLabel("");
+ downloadsInProgessLabel->setObjectName("NumDownloadsInProgressLabel");
+ downloadingItemLayout->addWidget(downloadsInProgessLabel);
+
+ if (m_downloadController->IsDownloadQueueEmpty())
{
- if (m_downloadController->IsDownloadQueueEmpty())
- {
- widget->hide();
- }
- else
- {
- widget->setUpdatesEnabled(false);
- // remove items
- QLayoutItem* layoutItem = nullptr;
- while ((layoutItem = downloadingItemLayout->takeAt(0)) != nullptr)
- {
- if (layoutItem->layout())
- {
- // Gem info row
- QLayoutItem* rowLayoutItem = nullptr;
- while ((rowLayoutItem = layoutItem->layout()->takeAt(0)) != nullptr)
- {
- rowLayoutItem->widget()->deleteLater();
- }
- layoutItem->layout()->deleteLater();
- }
- if (layoutItem->widget())
- {
- layoutItem->widget()->deleteLater();
- }
- }
-
- // Setup gem download rows
- const AZStd::vector& downloadQueue = m_downloadController->GetDownloadQueue();
-
- QLabel* downloadsInProgessLabel = new QLabel("");
- downloadsInProgessLabel->setText(
- QString("%1 %2").arg(downloadQueue.size()).arg(downloadQueue.size() == 1 ? tr("download in progress...") : tr("downloads in progress...")));
- downloadingItemLayout->addWidget(downloadsInProgessLabel);
-
- for (int downloadingGemNumber = 0; downloadingGemNumber < downloadQueue.size(); ++downloadingGemNumber)
- {
- QHBoxLayout* nameProgressLayout = new QHBoxLayout();
-
- const QString& gemName = downloadQueue[downloadingGemNumber];
- TagWidget* newTag = new TagWidget({gemName, gemName});
- nameProgressLayout->addWidget(newTag);
-
- QLabel* progress = new QLabel(downloadingGemNumber == 0? QString("%1%").arg(downloadProgress) : tr("Queued"));
- nameProgressLayout->addWidget(progress);
-
- QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
- nameProgressLayout->addSpacerItem(spacer);
-
- QLabel* cancelText = new QLabel(QString("Cancel").arg(gemName));
- cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
- connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated);
- nameProgressLayout->addWidget(cancelText);
- downloadingItemLayout->addLayout(nameProgressLayout);
-
- QProgressBar* downloadProgessBar = new QProgressBar();
- downloadingItemLayout->addWidget(downloadProgessBar);
- downloadProgessBar->setValue(downloadingGemNumber == 0 ? downloadProgress : 0);
- }
-
- widget->setUpdatesEnabled(true);
- widget->show();
- }
- };
-
- auto downloadEnded = [=](const QString& /*gemName*/, bool /*success*/)
+ m_downloadSectionWidget->hide();
+ }
+ else
{
- update(0); // update the list to remove the gem that has finished
- };
+ // Setup gem download rows for gems that are already in the queue
+ const AZStd::vector& downloadQueue = m_downloadController->GetDownloadQueue();
+
+ for (const QString& gemName : downloadQueue)
+ {
+ GemDownloadAdded(gemName);
+ }
+ }
+
// connect to download controller data changed
- connect(m_downloadController, &DownloadController::GemDownloadProgress, this, update);
- connect(m_downloadController, &DownloadController::Done, this, downloadEnded);
- update(0);
+ connect(m_downloadController, &DownloadController::GemDownloadAdded, this, &CartOverlayWidget::GemDownloadAdded);
+ connect(m_downloadController, &DownloadController::GemDownloadRemoved, this, &CartOverlayWidget::GemDownloadRemoved);
+ connect(m_downloadController, &DownloadController::GemDownloadProgress, this, &CartOverlayWidget::GemDownloadProgress);
+ connect(m_downloadController, &DownloadController::Done, this, &CartOverlayWidget::GemDownloadComplete);
+ }
+
+ void CartOverlayWidget::GemDownloadAdded(const QString& gemName)
+ {
+ // Containing widget for the current download item
+ QWidget* newGemDownloadWidget = new QWidget();
+ newGemDownloadWidget->setObjectName(gemName);
+ QVBoxLayout* downloadingGemLayout = new QVBoxLayout(newGemDownloadWidget);
+ newGemDownloadWidget->setLayout(downloadingGemLayout);
+
+ // Gem name, progress string, cancel
+ QHBoxLayout* nameProgressLayout = new QHBoxLayout(newGemDownloadWidget);
+ TagWidget* newTag = new TagWidget({gemName, gemName}, newGemDownloadWidget);
+ nameProgressLayout->addWidget(newTag);
+ QLabel* progress = new QLabel(tr("Queued"), newGemDownloadWidget);
+ progress->setObjectName("DownloadProgressLabel");
+ nameProgressLayout->addWidget(progress);
+ nameProgressLayout->addStretch();
+ QLabel* cancelText = new QLabel(tr("Cancel").arg(gemName), newGemDownloadWidget);
+ cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
+ connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated);
+ nameProgressLayout->addWidget(cancelText);
+ downloadingGemLayout->addLayout(nameProgressLayout);
+
+ // Progress bar
+ QProgressBar* downloadProgessBar = new QProgressBar(newGemDownloadWidget);
+ downloadProgessBar->setObjectName("DownloadProgressBar");
+ downloadingGemLayout->addWidget(downloadProgessBar);
+ downloadProgessBar->setValue(0);
+
+ m_downloadingListWidget->layout()->addWidget(newGemDownloadWidget);
+
+ const AZStd::vector& downloadQueue = m_downloadController->GetDownloadQueue();
+ QLabel* numDownloads = m_downloadingListWidget->findChild("NumDownloadsInProgressLabel");
+ numDownloads->setText(QString("%1 %2")
+ .arg(downloadQueue.size())
+ .arg(downloadQueue.size() == 1 ? tr("download in progress...") : tr("downloads in progress...")));
+
+ m_downloadingListWidget->show();
+ }
+
+ void CartOverlayWidget::GemDownloadRemoved(const QString& gemName)
+ {
+ QWidget* gemToRemove = m_downloadingListWidget->findChild(gemName);
+ if (gemToRemove)
+ {
+ gemToRemove->deleteLater();
+ }
+
+ if (m_downloadController->IsDownloadQueueEmpty())
+ {
+ m_downloadSectionWidget->hide();
+ }
+ else
+ {
+ size_t downloadQueueSize = m_downloadController->GetDownloadQueue().size();
+ QLabel* numDownloads = m_downloadingListWidget->findChild("NumDownloadsInProgressLabel");
+ numDownloads->setText(QString("%1 %2")
+ .arg(downloadQueueSize)
+ .arg(downloadQueueSize == 1 ? tr("download in progress...") : tr("downloads in progress...")));
+ }
+ }
+
+ void CartOverlayWidget::GemDownloadProgress(const QString& gemName, int percentage)
+ {
+ QWidget* gemToUpdate = m_downloadingListWidget->findChild(gemName);
+ if (gemToUpdate)
+ {
+ QLabel* progressLabel = gemToUpdate->findChild("DownloadProgressLabel");
+ if (progressLabel)
+ {
+ progressLabel->setText(QString("%1%").arg(percentage));
+ }
+ QProgressBar* progressBar = gemToUpdate->findChild("DownloadProgressBar");
+ if (progressBar)
+ {
+ progressBar->setValue(percentage);
+ }
+ }
+ }
+
+ void CartOverlayWidget::GemDownloadComplete(const QString& gemName, bool /*success*/)
+ {
+ GemDownloadRemoved(gemName); // update the list to remove the gem that has finished
}
QVector CartOverlayWidget::GetTagsFromModelIndices(const QVector& gems) const
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h
index 6da78cce7a..f3242d6db7 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h
@@ -34,6 +34,13 @@ namespace O3DE::ProjectManager
public:
CartOverlayWidget(GemModel* gemModel, DownloadController* downloadController, QWidget* parent = nullptr);
+ ~CartOverlayWidget();
+
+ public slots:
+ void GemDownloadAdded(const QString& gemName);
+ void GemDownloadRemoved(const QString& gemName);
+ void GemDownloadProgress(const QString& gemName, int percentage);
+ void GemDownloadComplete(const QString& gemName, bool success);
private:
QVector GetTagsFromModelIndices(const QVector& gems) const;
@@ -47,6 +54,9 @@ namespace O3DE::ProjectManager
GemModel* m_gemModel = nullptr;
DownloadController* m_downloadController = nullptr;
+ QWidget* m_downloadSectionWidget = nullptr;
+ QWidget* m_downloadingListWidget = nullptr;
+
inline constexpr static int s_width = 240;
};
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp
index 79935ed235..732f4813a2 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp
@@ -90,6 +90,13 @@ namespace O3DE::ProjectManager
m_projectPath = projectPath;
m_gemModel->Clear();
m_gemsToRegisterWithProject.clear();
+
+ if (m_filterWidget)
+ {
+ // disconnect so we don't update the status filter for every gem we add
+ disconnect(m_gemModel, &GemModel::dataChanged, m_filterWidget, &GemFilterWidget::ResetGemStatusFilter);
+ }
+
FillModel(projectPath);
m_proxyModel->ResetFilters();
@@ -251,6 +258,7 @@ namespace O3DE::ProjectManager
if (added && GemModel::GetDownloadStatus(modelIndex) == GemInfo::DownloadStatus::NotDownloaded)
{
m_downloadController->AddGemDownload(GemModel::GetName(modelIndex));
+ GemModel::SetDownloadStatus(*m_proxyModel, m_proxyModel->mapFromSource(modelIndex), GemInfo::DownloadStatus::Downloading);
}
}
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp
index b608445d0f..acea6ce378 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp
@@ -221,7 +221,6 @@ namespace O3DE::ProjectManager
ResetGemStatusFilter();
ResetGemOriginFilter();
ResetTypeFilter();
- ResetPlatformFilter();
ResetFeatureFilter();
}
diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp
index 4a73b39ea0..021066e1c7 100644
--- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp
+++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp
@@ -1179,6 +1179,7 @@ namespace O3DE::ProjectManager
QString_To_Py_String(gemName), // gem name
pybind11::none(), // destination path
false, // skip auto register
+ false, // force
pybind11::cpp_function(
[this, gemProgressCallback](int progress)
{
diff --git a/Code/Tools/PythonBindingsExample/source/Application.cpp b/Code/Tools/PythonBindingsExample/source/Application.cpp
index ab1d1b5acf..cfb28d8e09 100644
--- a/Code/Tools/PythonBindingsExample/source/Application.cpp
+++ b/Code/Tools/PythonBindingsExample/source/Application.cpp
@@ -39,7 +39,6 @@ namespace PythonBindingsExample
AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusConnect();
// prepare the Python binding gem(s)
- CalculateExecutablePath();
Start(Descriptor());
AZ::SerializeContext* context;
diff --git a/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneBehaviorTests.cpp b/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneBehaviorTests.cpp
index 3bf75e2d9b..0478e6cdb2 100644
--- a/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneBehaviorTests.cpp
+++ b/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneBehaviorTests.cpp
@@ -368,7 +368,6 @@ namespace AZ::SceneAPI::Containers
MOCK_METHOD0(GetSerializeContext, AZ::SerializeContext* ());
MOCK_METHOD0(GetJsonRegistrationContext, AZ::JsonRegistrationContext* ());
MOCK_METHOD0(GetBehaviorContext, AZ::BehaviorContext* ());
- MOCK_CONST_METHOD0(GetAppRoot, const char*());
MOCK_CONST_METHOD0(GetEngineRoot, const char*());
MOCK_CONST_METHOD0(GetExecutableFolder, const char* ());
MOCK_CONST_METHOD1(QueryApplicationType, void(AZ::ApplicationTypeQuery&));
diff --git a/Code/Tools/SerializeContextTools/Converter.cpp b/Code/Tools/SerializeContextTools/Converter.cpp
index 6a8bebdbfc..294bf941ac 100644
--- a/Code/Tools/SerializeContextTools/Converter.cpp
+++ b/Code/Tools/SerializeContextTools/Converter.cpp
@@ -202,8 +202,6 @@ namespace AZ
bool skipSystem = commandLine->HasSwitch("skipsystem");
bool isDryRun = commandLine->HasSwitch("dryrun");
- const char* appRoot = const_cast(application).GetAppRoot();
-
PathDocumentContainer documents;
bool result = true;
const AZStd::string& filePath = application.GetConfigFilePath();
@@ -230,7 +228,7 @@ namespace AZ
}
auto callback =
- [&result, skipGems, skipSystem, &configurationName, sourceGameFolder, &appRoot, &documents, &convertSettings, &verifySettings]
+ [&result, skipGems, skipSystem, &configurationName, sourceGameFolder, &documents, &convertSettings, &verifySettings]
(void* classPtr, const Uuid& classId, SerializeContext* context)
{
if (classId == azrtti_typeid())
@@ -238,7 +236,7 @@ namespace AZ
if (!skipSystem)
{
result = ConvertSystemSettings(documents, *reinterpret_cast(classPtr),
- configurationName, sourceGameFolder, appRoot) && result;
+ configurationName, sourceGameFolder) && result;
}
// Cleanup the Serialized Element to allow any classes within the element's hierarchy to delete
@@ -443,7 +441,7 @@ namespace AZ
}
bool Converter::ConvertSystemSettings(PathDocumentContainer& documents, const ComponentApplication::Descriptor& descriptor,
- const AZStd::string& configurationName, const AZ::IO::PathView& projectFolder, [[maybe_unused]] const AZStd::string& applicationRoot)
+ const AZStd::string& configurationName, const AZ::IO::PathView& projectFolder)
{
AZ::IO::FixedMaxPath memoryFilePath{ projectFolder };
memoryFilePath /= "Registry";
diff --git a/Code/Tools/SerializeContextTools/Converter.h b/Code/Tools/SerializeContextTools/Converter.h
index 6c8f6c70fb..7d30ca2a3a 100644
--- a/Code/Tools/SerializeContextTools/Converter.h
+++ b/Code/Tools/SerializeContextTools/Converter.h
@@ -43,7 +43,7 @@ namespace AZ
using PathDocumentContainer = AZStd::vector;
static bool ConvertSystemSettings(PathDocumentContainer& documents, const ComponentApplication::Descriptor& descriptor,
- const AZStd::string& configurationName, const AZ::IO::PathView& projectFolder, const AZStd::string& applicationRoot);
+ const AZStd::string& configurationName, const AZ::IO::PathView& projectFolder);
static bool ConvertSystemComponents(PathDocumentContainer& documents, const Entity& entity,
const AZStd::string& configurationName, const AZ::IO::PathView& projectFolder,
const JsonSerializerSettings& convertSettings, const JsonDeserializerSettings& verifySettings);
diff --git a/Gems/AWSClientAuth/Code/Tests/AWSClientAuthGemMock.h b/Gems/AWSClientAuth/Code/Tests/AWSClientAuthGemMock.h
index 1d2e8bad42..19314035c4 100644
--- a/Gems/AWSClientAuth/Code/Tests/AWSClientAuthGemMock.h
+++ b/Gems/AWSClientAuth/Code/Tests/AWSClientAuthGemMock.h
@@ -608,7 +608,6 @@ namespace AWSClientAuthUnitTest
AZ::Entity* FindEntity(const AZ::EntityId&) override { return nullptr; }
AZ::BehaviorContext* GetBehaviorContext() override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
- const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
void QueryApplicationType(AZ::ApplicationTypeQuery& /*appType*/) const override {}
diff --git a/Gems/AWSMetrics/Code/Include/Private/MetricsAttribute.h b/Gems/AWSMetrics/Code/Include/Public/MetricsAttribute.h
similarity index 100%
rename from Gems/AWSMetrics/Code/Include/Private/MetricsAttribute.h
rename to Gems/AWSMetrics/Code/Include/Public/MetricsAttribute.h
diff --git a/Gems/AWSMetrics/Code/awsmetrics_files.cmake b/Gems/AWSMetrics/Code/awsmetrics_files.cmake
index b51235c957..b1a3a647df 100644
--- a/Gems/AWSMetrics/Code/awsmetrics_files.cmake
+++ b/Gems/AWSMetrics/Code/awsmetrics_files.cmake
@@ -8,6 +8,7 @@
set(FILES
Include/Public/AWSMetricsBus.h
+ Include/Public/MetricsAttribute.h
Include/Private/AWSMetricsConstant.h
Include/Private/AWSMetricsServiceApi.h
Include/Private/AWSMetricsSystemComponent.h
@@ -15,7 +16,6 @@ set(FILES
Include/Private/DefaultClientIdProvider.h
Include/Private/GlobalStatistics.h
Include/Private/IdentityProvider.h
- Include/Private/MetricsAttribute.h
Include/Private/MetricsEvent.h
Include/Private/MetricsEventBuilder.h
Include/Private/MetricsManager.h
diff --git a/Gems/AssetValidation/Code/Source/AssetValidationSystemComponent.cpp b/Gems/AssetValidation/Code/Source/AssetValidationSystemComponent.cpp
index 56f28856af..8f8fb48212 100644
--- a/Gems/AssetValidation/Code/Source/AssetValidationSystemComponent.cpp
+++ b/Gems/AssetValidation/Code/Source/AssetValidationSystemComponent.cpp
@@ -439,13 +439,6 @@ namespace AssetValidation
bool GetDefaultSeedListFiles(AZStd::vector& defaultSeedListFiles)
{
- const char* engineRoot = nullptr;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
-
- const char* appRoot = nullptr;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(appRoot, &AzFramework::ApplicationRequests::GetAppRoot);
-
-
auto settingsRegistry = AZ::SettingsRegistry::Get();
AZ::SettingsRegistryInterface::FixedValueString gameFolder;
auto projectKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/project_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey);
@@ -509,30 +502,28 @@ namespace AssetValidation
AZ::Outcome AssetValidationSystemComponent::LoadSeedList(const char* seedPath, AZStd::string& seedListPath)
{
- AZStd::string absoluteSeedPath = seedPath;
+ AZ::IO::Path absoluteSeedPath = seedPath;
if (AZ::StringFunc::Path::IsRelative(seedPath))
{
- const char* appRoot = nullptr;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(appRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
+ AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath();
- if (!appRoot)
+ if (engineRoot.empty())
{
return AZ::Failure(AZStd::string("Couldn't get engine root"));
}
- absoluteSeedPath = AZStd::string::format("%s/%s", appRoot, seedPath);
+ absoluteSeedPath = (engineRoot / seedPath).String();
}
- AzFramework::StringFunc::Path::Normalize(absoluteSeedPath);
AzFramework::AssetSeedList seedList;
- if (!AZ::Utils::LoadObjectFromFileInPlace(absoluteSeedPath, seedList))
+ if (!AZ::Utils::LoadObjectFromFileInPlace(absoluteSeedPath.Native(), seedList))
{
return AZ::Failure(AZStd::string::format("Failed to load seed list %s", absoluteSeedPath.c_str()));
}
- seedListPath = absoluteSeedPath;
+ seedListPath = AZStd::move(absoluteSeedPath.Native());
return AZ::Success(seedList);
}
diff --git a/Gems/AssetValidation/Code/Tests/AssetValidationTestShared.h b/Gems/AssetValidation/Code/Tests/AssetValidationTestShared.h
index c4872ab425..8da3ae1b34 100644
--- a/Gems/AssetValidation/Code/Tests/AssetValidationTestShared.h
+++ b/Gems/AssetValidation/Code/Tests/AssetValidationTestShared.h
@@ -150,13 +150,13 @@ struct AssetValidationTest
auto projectPathKey = AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)
+ "/project_path";
- m_registry.Set(projectPathKey, (AZ::IO::FixedMaxPath(GetEngineRoot()) / "AutomatedTesting").Native());
+ m_registry.Set(projectPathKey, (AZ::IO::FixedMaxPath(m_tempDir.GetDirectory()) / "AutomatedTesting").Native());
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry);
// Set the engine root to the temporary directory and re-update the runtime file paths
auto enginePathKey = AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)
+ "/engine_path";
- m_registry.Set(enginePathKey, GetEngineRoot());
+ m_registry.Set(enginePathKey, m_tempDir.GetDirectory());
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry);
}
}
@@ -176,11 +176,6 @@ struct AssetValidationTest
AZ_Assert(false, "Not implemented");
}
- const char* GetEngineRoot() const override
- {
- return m_tempDir.GetDirectory();
- }
-
void SetUp() override
{
using namespace ::testing;
diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp
index d5b795a1fa..d0029ffc86 100644
--- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp
+++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp
@@ -111,7 +111,6 @@ namespace UnitTest
AZ::SerializeContext* GetSerializeContext() override { return m_context.get(); }
AZ::BehaviorContext* GetBehaviorContext() override { return nullptr; }
AZ::JsonRegistrationContext* GetJsonRegistrationContext() override { return m_jsonRegistrationContext.get(); }
- const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
void EnumerateEntities(const AZ::ComponentApplicationRequests::EntityCallback& /*callback*/) override {}
diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli
index 10526597cb..9f40e7ab8f 100644
--- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli
+++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli
@@ -37,6 +37,7 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject
float m_padding;
bool m_useReflectionProbe;
bool m_useParallaxCorrection;
+ float m_exposure;
};
ReflectionProbeData m_reflectionProbeData;
diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli
index d33a307dfe..3254b8e4ed 100644
--- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli
+++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli
@@ -85,12 +85,12 @@ void ApplyIBL(Surface surface, inout LightingData lightingData)
if(useIbl)
{
- float iblExposureFactor = pow(2.0, SceneSrg::m_iblExposure);
+ float globalIblExposure = pow(2.0, SceneSrg::m_iblExposure);
if(useDiffuseIbl)
{
float3 iblDiffuse = GetIblDiffuse(surface.normal, surface.albedo, lightingData.diffuseResponse);
- lightingData.diffuseLighting += (iblDiffuse * iblExposureFactor * lightingData.diffuseAmbientOcclusion);
+ lightingData.diffuseLighting += (iblDiffuse * globalIblExposure * lightingData.diffuseAmbientOcclusion);
}
if(useSpecularIbl)
@@ -116,7 +116,8 @@ void ApplyIBL(Surface surface, inout LightingData lightingData)
iblSpecular = iblSpecular * (1.0 - clearCoatResponse) * (1.0 - clearCoatResponse) + clearCoatIblSpecular;
}
- lightingData.specularLighting += (iblSpecular * iblExposureFactor);
+ float exposure = ObjectSrg::m_reflectionProbeData.m_useReflectionProbe ? pow(2.0, ObjectSrg::m_reflectionProbeData.m_exposure) : globalIblExposure;
+ lightingData.specularLighting += (iblSpecular * exposure);
}
}
}
diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Skin/SkinObjectSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Skin/SkinObjectSrg.azsli
index d0766c295d..99a32629ef 100644
--- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Skin/SkinObjectSrg.azsli
+++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Skin/SkinObjectSrg.azsli
@@ -46,6 +46,7 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject
float m_padding;
bool m_useReflectionProbe;
bool m_useParallaxCorrection;
+ float m_exposure;
};
ReflectionProbeData m_reflectionProbeData;
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl
index a0734caf02..e9333a4694 100644
--- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl
+++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl
@@ -81,7 +81,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
}
// apply exposure setting
- specular *= pow(2.0, SceneSrg::m_iblExposure);
+ specular *= pow(2.0, ObjectSrg::m_exposure);
PSOutput OUT;
OUT.m_color = float4(specular, 1.0f);
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli
index 8151ed2fd5..366dc691ed 100644
--- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli
+++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli
@@ -17,6 +17,7 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject
float3 m_outerObbHalfLengths;
float3 m_innerObbHalfLengths;
bool m_useParallaxCorrection;
+ float m_exposure;
TextureCube m_reflectionCubeMap;
float4x4 GetWorldMatrix()
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl
index ac97172f1f..138d29398e 100644
--- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl
+++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl
@@ -104,7 +104,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
blendWeight /= max(1.0f, blendWeightAllProbes);
// apply exposure setting
- specular *= pow(2.0, SceneSrg::m_iblExposure);
+ specular *= pow(2.0, ObjectSrg::m_exposure);
// apply blend weight for additive blending
specular *= blendWeight;
diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h
index 2ac184e2e0..23cd76ca20 100644
--- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h
+++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h
@@ -30,7 +30,7 @@ namespace AZ
class TransformServiceFeatureProcessor;
class RayTracingFeatureProcessor;
- class MeshDataInstance
+ class ModelDataInstance
{
friend class MeshFeatureProcessor;
friend class MeshLoader;
@@ -47,7 +47,7 @@ namespace AZ
public:
using ModelChangedEvent = MeshFeatureProcessorInterface::ModelChangedEvent;
- MeshLoader(const Data::Asset& modelAsset, MeshDataInstance* parent);
+ MeshLoader(const Data::Asset& modelAsset, ModelDataInstance* parent);
~MeshLoader();
ModelChangedEvent& GetModelChangedEvent();
@@ -68,7 +68,7 @@ namespace AZ
} };
MeshFeatureProcessorInterface::ModelChangedEvent m_modelChangedEvent;
Data::Asset m_modelAsset;
- MeshDataInstance* m_parent = nullptr;
+ ModelDataInstance* m_parent = nullptr;
};
void DeInit();
@@ -99,7 +99,8 @@ namespace AZ
//! A reference to the original model asset in case it got cloned before creating the model instance.
Data::Asset m_originalModelAsset;
- Data::Instance m_shaderResourceGroup;
+ //! List of object SRGs used by meshes in this model
+ AZStd::vector> m_objectSrgList;
AZStd::unique_ptr m_meshLoader;
RPI::Scene* m_scene = nullptr;
RHI::DrawItemSortKey m_sortKey;
@@ -152,7 +153,7 @@ namespace AZ
Data::Instance GetModel(const MeshHandle& meshHandle) const override;
Data::Asset GetModelAsset(const MeshHandle& meshHandle) const override;
- Data::Instance GetObjectSrg(const MeshHandle& meshHandle) const override;
+ const AZStd::vector>& GetObjectSrgs(const MeshHandle& meshHandle) const override;
void QueueObjectSrgForCompile(const MeshHandle& meshHandle) const override;
void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const Data::Instance& material) override;
void SetMaterialAssignmentMap(const MeshHandle& meshHandle, const MaterialAssignmentMap& materials) override;
@@ -195,7 +196,7 @@ namespace AZ
void OnRenderPipelineRemoved(RPI::RenderPipeline* pipeline) override;
AZStd::concurrency_checker m_meshDataChecker;
- StableDynamicArray m_meshData;
+ StableDynamicArray m_modelData;
TransformServiceFeatureProcessor* m_transformService;
RayTracingFeatureProcessor* m_rayTracingFeatureProcessor = nullptr;
AZ::RPI::ShaderSystemInterface::GlobalShaderOptionUpdatedEvent::Handler m_handleGlobalShaderOptionUpdate;
diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h
index cffbe5c3c5..356b1936ca 100644
--- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h
+++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h
@@ -20,7 +20,7 @@ namespace AZ
{
namespace Render
{
- class MeshDataInstance;
+ class ModelDataInstance;
//! Settings to apply to a mesh handle when acquiring it for the first time
struct MeshHandleDescriptor
@@ -40,7 +40,7 @@ namespace AZ
public:
AZ_RTTI(AZ::Render::MeshFeatureProcessorInterface, "{975D7F0C-2E7E-4819-94D0-D3C4E2024721}", FeatureProcessor);
- using MeshHandle = StableDynamicArrayHandle;
+ using MeshHandle = StableDynamicArrayHandle;
using ModelChangedEvent = Event>;
//! Acquires a model with an optional collection of material assignments.
@@ -61,12 +61,15 @@ namespace AZ
virtual Data::Instance GetModel(const MeshHandle& meshHandle) const = 0;
//! Gets the underlying RPI::ModelAsset for a meshHandle.
virtual Data::Asset GetModelAsset(const MeshHandle& meshHandle) const = 0;
- //! Gets the ObjectSrg for a meshHandle.
- //! Updating the ObjectSrg should be followed by a call to QueueObjectSrgForCompile,
- //! instead of compiling the srg directly. This way, if the srg has already been queued for compile,
- //! it will not be queued twice in the same frame. The ObjectSrg should not be updated during
+
+ //! Gets the ObjectSrgs for a meshHandle.
+ //! Updating the ObjectSrgs should be followed by a call to QueueObjectSrgForCompile,
+ //! instead of compiling the srgs directly. This way, if the srgs have already been queued for compile,
+ //! they will not be queued twice in the same frame. The ObjectSrgs should not be updated during
//! Simulate, or it will create a race between updating the data and the call to Compile
- virtual Data::Instance GetObjectSrg(const MeshHandle& meshHandle) const = 0;
+ //! Cases where there may be multiple ObjectSrgs: if a model has multiple submeshes and those submeshes use different
+ //! materials with different object SRGs.
+ virtual const AZStd::vector>& GetObjectSrgs(const MeshHandle& meshHandle) const = 0;
//! Queues the object srg for compile.
virtual void QueueObjectSrgForCompile(const MeshHandle& meshHandle) const = 0;
//! Sets the MaterialAssignmentMap for a meshHandle, using just a single material for the DefaultMaterialAssignmentId.
diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h
index 5efd235a67..ded36f5496 100644
--- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h
+++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h
@@ -39,6 +39,8 @@ namespace AZ
bool IsCubeMapReferenced(const AZStd::string& relativePath) override;
bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const override { return (probe.get() != nullptr); }
void ShowProbeVisualization(const ReflectionProbeHandle& probe, bool showVisualization) override;
+ void SetRenderExposure(const ReflectionProbeHandle& probe, float renderExposure) override;
+ void SetBakeExposure(const ReflectionProbeHandle& probe, float bakeExposure) override;
// FeatureProcessor overrides
void Activate() override;
diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h
index 4eb2130b1b..80c92281ea 100644
--- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h
+++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h
@@ -50,6 +50,8 @@ namespace AZ
virtual bool IsCubeMapReferenced(const AZStd::string& relativePath) = 0;
virtual bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const = 0;
virtual void ShowProbeVisualization(const ReflectionProbeHandle& probe, bool showVisualization) = 0;
+ virtual void SetRenderExposure(const ReflectionProbeHandle& probe, float renderExposure) = 0;
+ virtual void SetBakeExposure(const ReflectionProbeHandle& probe, float bakeExposure) = 0;
};
} // namespace Render
} // namespace AZ
diff --git a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h
index 35e399997f..2c818d3c9b 100644
--- a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h
+++ b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h
@@ -19,7 +19,7 @@ namespace UnitTest
MOCK_METHOD1(CloneMesh, MeshHandle(const MeshHandle&));
MOCK_CONST_METHOD1(GetModel, AZStd::intrusive_ptr(const MeshHandle&));
MOCK_CONST_METHOD1(GetModelAsset, AZ::Data::Asset(const MeshHandle&));
- MOCK_CONST_METHOD1(GetObjectSrg, AZStd::intrusive_ptr(const MeshHandle&));
+ MOCK_CONST_METHOD1(GetObjectSrgs, const AZStd::vector>&(const MeshHandle&));
MOCK_CONST_METHOD1(QueueObjectSrgForCompile, void(const MeshHandle&));
MOCK_CONST_METHOD1(GetMaterialAssignmentMap, const AZ::Render::MaterialAssignmentMap&(const MeshHandle&));
MOCK_METHOD2(ConnectModelChangeEventHandler, void(const MeshHandle&, ModelChangedEvent::Handler&));
diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp
index b6c6910fd3..410c80dbdc 100644
--- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp
@@ -1056,7 +1056,7 @@ namespace AZ
// if the shadow is rendering in an EnvironmentCubeMapPass it also needs to be a ReflectiveCubeMap view,
// to filter out shadows from objects that are excluded from the cubemap
RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassClass();
- passFilter.SetOwenrScene(GetParentScene()); // only handles passes for this scene
+ passFilter.SetOwnerScene(GetParentScene()); // only handles passes for this scene
RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [&usageFlags]([[maybe_unused]] RPI::Pass* pass) -> RPI::PassFilterExecutionFlow
{
usageFlags |= RPI::View::UsageReflectiveCubeMap;
diff --git a/Gems/Atom/Feature/Common/Code/Source/LuxCore/LuxCoreRenderer.cpp b/Gems/Atom/Feature/Common/Code/Source/LuxCore/LuxCoreRenderer.cpp
index c753079d5b..ef3f33d1c3 100644
--- a/Gems/Atom/Feature/Common/Code/Source/LuxCore/LuxCoreRenderer.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/LuxCore/LuxCoreRenderer.cpp
@@ -13,6 +13,7 @@
#include
#include
#include
+#include
#include
#include
@@ -295,14 +296,12 @@ namespace AZ
}
// Run luxcoreui.exe
- AZStd::string luxCoreExeFullPath;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(luxCoreExeFullPath, &AzFramework::ApplicationRequests::GetAppRoot);
- luxCoreExeFullPath = luxCoreExeFullPath + AZ_TRAIT_LUXCORE_EXEPATH;
- AzFramework::StringFunc::Path::Normalize(luxCoreExeFullPath);
+ AZ::IO::FixedMaxPath luxCoreExeFullPath = AZ::Utils::GetEnginePath();
+ luxCoreExeFullPath /= AZ_TRAIT_LUXCORE_EXEPATH;
AZStd::string commandLine = "-o " + AZStd::string(resolvedPath) + "/render.cfg";
- LuxCoreUI::LaunchLuxCoreUI(luxCoreExeFullPath, commandLine);
+ LuxCoreUI::LaunchLuxCoreUI(luxCoreExeFullPath.String(), commandLine);
}
}
}
diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp
index c7fb19bc5d..112eff64a8 100644
--- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp
@@ -67,7 +67,7 @@ namespace AZ
m_handleGlobalShaderOptionUpdate.Disconnect();
DisableSceneNotification();
- AZ_Warning("MeshFeatureProcessor", m_meshData.size() == 0,
+ AZ_Warning("MeshFeatureProcessor", m_modelData.size() == 0,
"Deactivaing the MeshFeatureProcessor, but there are still outstanding mesh handles.\n"
);
m_transformService = nullptr;
@@ -81,7 +81,7 @@ namespace AZ
AZStd::concurrency_check_scope scopeCheck(m_meshDataChecker);
- const auto iteratorRanges = m_meshData.GetParallelRanges();
+ const auto iteratorRanges = m_modelData.GetParallelRanges();
AZ::JobCompletion jobCompletion;
for (const auto& iteratorRange : iteratorRanges)
{
@@ -125,11 +125,11 @@ namespace AZ
m_forceRebuildDrawPackets = false;
// CullingSystem::RegisterOrUpdateCullable() is not threadsafe, so need to do those updates in a single thread
- for (MeshDataInstance& meshDataInstance : m_meshData)
+ for (ModelDataInstance& modelDataInstance : m_modelData)
{
- if (meshDataInstance.m_model && meshDataInstance.m_cullBoundsNeedsUpdate)
+ if (modelDataInstance.m_model && modelDataInstance.m_cullBoundsNeedsUpdate)
{
- meshDataInstance.UpdateCullBounds(m_transformService);
+ modelDataInstance.UpdateCullBounds(m_transformService);
}
}
}
@@ -151,14 +151,14 @@ namespace AZ
AZ_PROFILE_SCOPE(AzRender, "MeshFeatureProcessor: AcquireMesh");
// don't need to check the concurrency during emplace() because the StableDynamicArray won't move the other elements during insertion
- MeshHandle meshDataHandle = m_meshData.emplace();
+ MeshHandle meshDataHandle = m_modelData.emplace();
meshDataHandle->m_descriptor = descriptor;
meshDataHandle->m_scene = GetParentScene();
meshDataHandle->m_materialAssignments = materials;
meshDataHandle->m_objectId = m_transformService->ReserveObjectId();
meshDataHandle->m_originalModelAsset = descriptor.m_modelAsset;
- meshDataHandle->m_meshLoader = AZStd::make_unique(descriptor.m_modelAsset, &*meshDataHandle);
+ meshDataHandle->m_meshLoader = AZStd::make_unique(descriptor.m_modelAsset, &*meshDataHandle);
return meshDataHandle;
}
@@ -183,7 +183,7 @@ namespace AZ
m_transformService->ReleaseObjectId(meshHandle->m_objectId);
AZStd::concurrency_check_scope scopeCheck(m_meshDataChecker);
- m_meshData.erase(meshHandle);
+ m_modelData.erase(meshHandle);
return true;
}
@@ -215,9 +215,10 @@ namespace AZ
return {};
}
- Data::Instance MeshFeatureProcessor::GetObjectSrg(const MeshHandle& meshHandle) const
+ const AZStd::vector>& MeshFeatureProcessor::GetObjectSrgs(const MeshHandle& meshHandle) const
{
- return meshHandle.IsValid() ? meshHandle->m_shaderResourceGroup : nullptr;
+ static AZStd::vector> staticEmptyList;
+ return meshHandle.IsValid() ? meshHandle->m_objectSrgList : staticEmptyList;
}
void MeshFeatureProcessor::QueueObjectSrgForCompile(const MeshHandle& meshHandle) const
@@ -274,9 +275,9 @@ namespace AZ
{
if (meshHandle.IsValid())
{
- MeshDataInstance& meshData = *meshHandle;
- meshData.m_cullBoundsNeedsUpdate = true;
- meshData.m_objectSrgNeedsUpdate = true;
+ ModelDataInstance& modelData = *meshHandle;
+ modelData.m_cullBoundsNeedsUpdate = true;
+ modelData.m_objectSrgNeedsUpdate = true;
m_transformService->SetTransformForId(meshHandle->m_objectId, transform, nonUniformScale);
@@ -292,10 +293,10 @@ namespace AZ
{
if (meshHandle.IsValid())
{
- MeshDataInstance& meshData = *meshHandle;
- meshData.m_aabb = localAabb;
- meshData.m_cullBoundsNeedsUpdate = true;
- meshData.m_objectSrgNeedsUpdate = true;
+ ModelDataInstance& modelData = *meshHandle;
+ modelData.m_aabb = localAabb;
+ modelData.m_cullBoundsNeedsUpdate = true;
+ modelData.m_objectSrgNeedsUpdate = true;
}
};
@@ -465,7 +466,7 @@ namespace AZ
void MeshFeatureProcessor::UpdateMeshReflectionProbes()
{
// we need to rebuild the Srg for any meshes that are using the forward pass IBL specular option
- for (auto& meshInstance : m_meshData)
+ for (auto& meshInstance : m_modelData)
{
if (meshInstance.m_descriptor.m_useForwardPassIblSpecular)
{
@@ -474,14 +475,14 @@ namespace AZ
}
}
- // MeshDataInstance::MeshLoader...
- MeshDataInstance::MeshLoader::MeshLoader(const Data::Asset& modelAsset, MeshDataInstance* parent)
+ // ModelDataInstance::MeshLoader...
+ ModelDataInstance::MeshLoader::MeshLoader(const Data::Asset& modelAsset, ModelDataInstance* parent)
: m_modelAsset(modelAsset)
, m_parent(parent)
{
if (!m_modelAsset.GetId().IsValid())
{
- AZ_Error("MeshDataInstance::MeshLoader", false, "Invalid model asset Id.");
+ AZ_Error("ModelDataInstance::MeshLoader", false, "Invalid model asset Id.");
return;
}
@@ -494,19 +495,19 @@ namespace AZ
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
}
- MeshDataInstance::MeshLoader::~MeshLoader()
+ ModelDataInstance::MeshLoader::~MeshLoader()
{
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
Data::AssetBus::Handler::BusDisconnect();
}
- MeshFeatureProcessorInterface::ModelChangedEvent& MeshDataInstance::MeshLoader::GetModelChangedEvent()
+ MeshFeatureProcessorInterface::ModelChangedEvent& ModelDataInstance::MeshLoader::GetModelChangedEvent()
{
return m_modelChangedEvent;
}
//! AssetBus::Handler overrides...
- void MeshDataInstance::MeshLoader::OnAssetReady(Data::Asset asset)
+ void ModelDataInstance::MeshLoader::OnAssetReady(Data::Asset asset)
{
Data::Asset modelAsset = asset;
@@ -527,7 +528,7 @@ namespace AZ
}
else
{
- AZ_Error("MeshDataInstance", false, "Cannot clone model for '%s'. Cloth simulation results won't be individual per entity.", modelAsset->GetName().GetCStr());
+ AZ_Error("ModelDataInstance", false, "Cannot clone model for '%s'. Cloth simulation results won't be individual per entity.", modelAsset->GetName().GetCStr());
model = RPI::Model::FindOrCreate(modelAsset);
}
}
@@ -547,29 +548,29 @@ namespace AZ
{
//when running with null renderer, the RPI::Model::FindOrCreate(...) is expected to return nullptr, so suppress this error.
AZ_Error(
- "MeshDataInstance::OnAssetReady", RHI::IsNullRenderer(), "Failed to create model instance for '%s'",
+ "ModelDataInstance::OnAssetReady", RHI::IsNullRenderer(), "Failed to create model instance for '%s'",
asset.GetHint().c_str());
}
}
- void MeshDataInstance::MeshLoader::OnModelReloaded(Data::Asset asset)
+ void ModelDataInstance::MeshLoader::OnModelReloaded(Data::Asset asset)
{
OnAssetReady(asset);
}
- void MeshDataInstance::MeshLoader::OnAssetError(Data::Asset asset)
+ void ModelDataInstance::MeshLoader::OnAssetError(Data::Asset asset)
{
// Note: m_modelAsset and asset represents same asset, but only m_modelAsset contains the file path in its hint from serialization
AZ_Error(
- "MeshDataInstance::MeshLoader", false, "Failed to load asset %s. It may be missing, or not be finished processing",
+ "ModelDataInstance::MeshLoader", false, "Failed to load asset %s. It may be missing, or not be finished processing",
m_modelAsset.GetHint().c_str());
AzFramework::AssetSystemRequestBus::Broadcast(
&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetByUuid, m_modelAsset.GetId().m_guid);
}
- void MeshDataInstance::MeshLoader::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId)
+ void ModelDataInstance::MeshLoader::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId)
{
if (assetId == m_modelAsset.GetId())
{
@@ -584,7 +585,7 @@ namespace AZ
}
}
- void MeshDataInstance::MeshLoader::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId)
+ void ModelDataInstance::MeshLoader::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId)
{
if (assetId == m_modelAsset.GetId())
{
@@ -599,9 +600,9 @@ namespace AZ
}
}
- // MeshDataInstance...
+ // ModelDataInstance...
- void MeshDataInstance::DeInit()
+ void ModelDataInstance::DeInit()
{
m_scene->GetCullingScene()->UnregisterCullable(m_cullable);
@@ -609,11 +610,11 @@ namespace AZ
m_drawPacketListsByLod.clear();
m_materialAssignments.clear();
- m_shaderResourceGroup = {};
+ m_objectSrgList = {};
m_model = {};
}
- void MeshDataInstance::Init(Data::Instance model)
+ void ModelDataInstance::Init(Data::Instance model)
{
m_model = model;
const size_t modelLodCount = m_model->GetLodCount();
@@ -623,11 +624,11 @@ namespace AZ
BuildDrawPacketList(modelLodIndex);
}
- if (m_shaderResourceGroup)
+ for(auto& objectSrg : m_objectSrgList)
{
// Set object Id once since it never changes
RHI::ShaderInputNameIndex objectIdIndex = "m_objectId";
- m_shaderResourceGroup->SetConstant(objectIdIndex, m_objectId.GetIndex());
+ objectSrg->SetConstant(objectIdIndex, m_objectId.GetIndex());
objectIdIndex.AssertValid();
}
@@ -643,12 +644,12 @@ namespace AZ
m_objectSrgNeedsUpdate = true;
}
- void MeshDataInstance::BuildDrawPacketList(size_t modelLodIndex)
+ void ModelDataInstance::BuildDrawPacketList(size_t modelLodIndex)
{
RPI::ModelLod& modelLod = *m_model->GetLods()[modelLodIndex];
const size_t meshCount = modelLod.GetMeshes().size();
- MeshDataInstance::DrawPacketList& drawPacketListOut = m_drawPacketListsByLod[modelLodIndex];
+ ModelDataInstance::DrawPacketList& drawPacketListOut = m_drawPacketListsByLod[modelLodIndex];
drawPacketListOut.clear();
drawPacketListOut.reserve(meshCount);
@@ -682,27 +683,32 @@ namespace AZ
continue;
}
- if (m_shaderResourceGroup && m_shaderResourceGroup->GetLayout()->GetHash() != objectSrgLayout->GetHash())
+ Data::Instance meshObjectSrg;
+
+ // See if the object SRG for this mesh is already in our list of object SRGs
+ for (auto& objectSrgIter : m_objectSrgList)
{
- AZ_Warning("MeshFeatureProcessor", false, "All materials on a model must use the same per-object ShaderResourceGroup. Skipping.");
- continue;
+ if (objectSrgIter->GetLayout()->GetHash() == objectSrgLayout->GetHash())
+ {
+ meshObjectSrg = objectSrgIter;
+ }
}
- // The first time we find the per-surface SRG asset we create an instance and store it
- // in shaderResourceGroupInOut. All of the Model's draw packets will use this same instance.
- if (!m_shaderResourceGroup)
+ // If the object SRG for this mesh was not already in the list, create it and add it to the list
+ if (!meshObjectSrg)
{
auto& shaderAsset = material->GetAsset()->GetMaterialTypeAsset()->GetShaderAssetForObjectSrg();
- m_shaderResourceGroup = RPI::ShaderResourceGroup::Create(shaderAsset, objectSrgLayout->GetName());
- if (!m_shaderResourceGroup)
+ meshObjectSrg = RPI::ShaderResourceGroup::Create(shaderAsset, objectSrgLayout->GetName());
+ if (!meshObjectSrg)
{
AZ_Warning("MeshFeatureProcessor", false, "Failed to create a new shader resource group, skipping.");
continue;
}
+ m_objectSrgList.push_back(meshObjectSrg);
}
// setup the mesh draw packet
- RPI::MeshDrawPacket drawPacket(modelLod, meshIndex, material, m_shaderResourceGroup, materialAssignment.m_matModUvOverrides);
+ RPI::MeshDrawPacket drawPacket(modelLod, meshIndex, material, meshObjectSrg, materialAssignment.m_matModUvOverrides);
// set the shader option to select forward pass IBL specular if necessary
if (!drawPacket.SetShaderOption(AZ::Name("o_meshUseForwardPassIBLSpecular"), AZ::RPI::ShaderOptionValue{ m_descriptor.m_useForwardPassIblSpecular }))
@@ -726,7 +732,7 @@ namespace AZ
}
}
- void MeshDataInstance::SetRayTracingData()
+ void ModelDataInstance::SetRayTracingData()
{
if (!m_model)
{
@@ -993,7 +999,7 @@ namespace AZ
rayTracingFeatureProcessor->SetMesh(m_objectId, m_model->GetModelAsset()->GetId(), subMeshes);
}
- void MeshDataInstance::RemoveRayTracingData()
+ void ModelDataInstance::RemoveRayTracingData()
{
// remove from ray tracing
RayTracingFeatureProcessor* rayTracingFeatureProcessor = m_scene->GetFeatureProcessor();
@@ -1003,7 +1009,7 @@ namespace AZ
}
}
- void MeshDataInstance::SetSortKey(RHI::DrawItemSortKey sortKey)
+ void ModelDataInstance::SetSortKey(RHI::DrawItemSortKey sortKey)
{
m_sortKey = sortKey;
for (auto& drawPacketList : m_drawPacketListsByLod)
@@ -1015,24 +1021,24 @@ namespace AZ
}
}
- RHI::DrawItemSortKey MeshDataInstance::GetSortKey() const
+ RHI::DrawItemSortKey ModelDataInstance::GetSortKey() const
{
return m_sortKey;
}
- void MeshDataInstance::SetMeshLodConfiguration(RPI::Cullable::LodConfiguration meshLodConfig)
+ void ModelDataInstance::SetMeshLodConfiguration(RPI::Cullable::LodConfiguration meshLodConfig)
{
m_cullable.m_lodData.m_lodConfiguration = meshLodConfig;
}
- RPI::Cullable::LodConfiguration MeshDataInstance::GetMeshLodConfiguration() const
+ RPI::Cullable::LodConfiguration ModelDataInstance::GetMeshLodConfiguration() const
{
return m_cullable.m_lodData.m_lodConfiguration;
}
- void MeshDataInstance::UpdateDrawPackets(bool forceUpdate /*= false*/)
+ void ModelDataInstance::UpdateDrawPackets(bool forceUpdate /*= false*/)
{
- AZ_PROFILE_SCOPE(AzRender, "MeshDataInstance:: UpdateDrawPackets");
+ AZ_PROFILE_SCOPE(AzRender, "ModelDataInstance:: UpdateDrawPackets");
for (auto& drawPacketList : m_drawPacketListsByLod)
{
for (auto& drawPacket : drawPacketList)
@@ -1045,9 +1051,9 @@ namespace AZ
}
}
- void MeshDataInstance::BuildCullable()
+ void ModelDataInstance::BuildCullable()
{
- AZ_PROFILE_SCOPE(AzRender, "MeshDataInstance: BuildCullable");
+ AZ_PROFILE_SCOPE(AzRender, "ModelDataInstance: BuildCullable");
AZ_Assert(m_cullableNeedsRebuild, "This function only needs to be called if the cullable to be rebuilt");
AZ_Assert(m_model, "The model has not finished loading yet");
@@ -1122,9 +1128,9 @@ namespace AZ
m_cullBoundsNeedsUpdate = true;
}
- void MeshDataInstance::UpdateCullBounds(const TransformServiceFeatureProcessor* transformService)
+ void ModelDataInstance::UpdateCullBounds(const TransformServiceFeatureProcessor* transformService)
{
- AZ_PROFILE_SCOPE(AzRender, "MeshDataInstance: UpdateCullBounds");
+ AZ_PROFILE_SCOPE(AzRender, "ModelDataInstance: UpdateCullBounds");
AZ_Assert(m_cullBoundsNeedsUpdate, "This function only needs to be called if the culling bounds need to be rebuilt");
AZ_Assert(m_model, "The model has not finished loading yet");
@@ -1148,70 +1154,74 @@ namespace AZ
m_cullBoundsNeedsUpdate = false;
}
- void MeshDataInstance::UpdateObjectSrg()
+ void ModelDataInstance::UpdateObjectSrg()
{
- if (!m_shaderResourceGroup)
+ for (auto& objectSrg : m_objectSrgList)
{
- return;
+ ReflectionProbeFeatureProcessor* reflectionProbeFeatureProcessor = m_scene->GetFeatureProcessor();
+
+ if (reflectionProbeFeatureProcessor && (m_descriptor.m_useForwardPassIblSpecular || m_hasForwardPassIblSpecularMaterial))
+ {
+ // retrieve probe constant indices
+ AZ::RHI::ShaderInputConstantIndex modelToWorldConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorld"));
+ AZ_Error("ModelDataInstance", modelToWorldConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
+
+ AZ::RHI::ShaderInputConstantIndex modelToWorldInverseConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorldInverse"));
+ AZ_Error("ModelDataInstance", modelToWorldInverseConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
+
+ AZ::RHI::ShaderInputConstantIndex outerObbHalfLengthsConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerObbHalfLengths"));
+ AZ_Error("ModelDataInstance", outerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
+
+ AZ::RHI::ShaderInputConstantIndex innerObbHalfLengthsConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerObbHalfLengths"));
+ AZ_Error("ModelDataInstance", innerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
+
+ AZ::RHI::ShaderInputConstantIndex useReflectionProbeConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useReflectionProbe"));
+ AZ_Error("ModelDataInstance", useReflectionProbeConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
+
+ AZ::RHI::ShaderInputConstantIndex useParallaxCorrectionConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useParallaxCorrection"));
+ AZ_Error("ModelDataInstance", useParallaxCorrectionConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
+
+ AZ::RHI::ShaderInputConstantIndex exposureConstantIndex = objectSrg->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_exposure"));
+ AZ_Error("ModelDataInstance", exposureConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
+
+ // retrieve probe cubemap index
+ Name reflectionCubeMapImageName = Name("m_reflectionProbeCubeMap");
+ RHI::ShaderInputImageIndex reflectionCubeMapImageIndex = objectSrg->FindShaderInputImageIndex(reflectionCubeMapImageName);
+ AZ_Error("ModelDataInstance", reflectionCubeMapImageIndex.IsValid(), "Failed to find shader image index [%s]", reflectionCubeMapImageName.GetCStr());
+
+ // retrieve the list of probes that contain the centerpoint of the mesh
+ TransformServiceFeatureProcessor* transformServiceFeatureProcessor = m_scene->GetFeatureProcessor();
+ Transform transform = transformServiceFeatureProcessor->GetTransformForId(m_objectId);
+
+ ReflectionProbeFeatureProcessor::ReflectionProbeVector reflectionProbes;
+ reflectionProbeFeatureProcessor->FindReflectionProbes(transform.GetTranslation(), reflectionProbes);
+
+ if (!reflectionProbes.empty() && reflectionProbes[0])
+ {
+ objectSrg->SetConstant(modelToWorldConstantIndex, reflectionProbes[0]->GetTransform());
+ objectSrg->SetConstant(modelToWorldInverseConstantIndex, Matrix3x4::CreateFromTransform(reflectionProbes[0]->GetTransform()).GetInverseFull());
+ objectSrg->SetConstant(outerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetOuterObbWs().GetHalfLengths());
+ objectSrg->SetConstant(innerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetInnerObbWs().GetHalfLengths());
+ objectSrg->SetConstant(useReflectionProbeConstantIndex, true);
+ objectSrg->SetConstant(useParallaxCorrectionConstantIndex, reflectionProbes[0]->GetUseParallaxCorrection());
+ objectSrg->SetConstant(exposureConstantIndex, reflectionProbes[0]->GetRenderExposure());
+
+ objectSrg->SetImage(reflectionCubeMapImageIndex, reflectionProbes[0]->GetCubeMapImage());
+ }
+ else
+ {
+ objectSrg->SetConstant(useReflectionProbeConstantIndex, false);
+ }
+ }
+
+ objectSrg->Compile();
}
- ReflectionProbeFeatureProcessor* reflectionProbeFeatureProcessor = m_scene->GetFeatureProcessor();
-
- if (reflectionProbeFeatureProcessor && (m_descriptor.m_useForwardPassIblSpecular || m_hasForwardPassIblSpecularMaterial))
- {
- // retrieve probe constant indices
- AZ::RHI::ShaderInputConstantIndex modelToWorldConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorld"));
- AZ_Error("MeshDataInstance", modelToWorldConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
-
- AZ::RHI::ShaderInputConstantIndex modelToWorldInverseConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorldInverse"));
- AZ_Error("MeshDataInstance", modelToWorldInverseConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
-
- AZ::RHI::ShaderInputConstantIndex outerObbHalfLengthsConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerObbHalfLengths"));
- AZ_Error("MeshDataInstance", outerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
-
- AZ::RHI::ShaderInputConstantIndex innerObbHalfLengthsConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerObbHalfLengths"));
- AZ_Error("MeshDataInstance", innerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
-
- AZ::RHI::ShaderInputConstantIndex useReflectionProbeConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useReflectionProbe"));
- AZ_Error("MeshDataInstance", useReflectionProbeConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
-
- AZ::RHI::ShaderInputConstantIndex useParallaxCorrectionConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useParallaxCorrection"));
- AZ_Error("MeshDataInstance", useParallaxCorrectionConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index");
-
- // retrieve probe cubemap index
- Name reflectionCubeMapImageName = Name("m_reflectionProbeCubeMap");
- RHI::ShaderInputImageIndex reflectionCubeMapImageIndex = m_shaderResourceGroup->FindShaderInputImageIndex(reflectionCubeMapImageName);
- AZ_Error("MeshDataInstance", reflectionCubeMapImageIndex.IsValid(), "Failed to find shader image index [%s]", reflectionCubeMapImageName.GetCStr());
-
- // retrieve the list of probes that contain the centerpoint of the mesh
- TransformServiceFeatureProcessor* transformServiceFeatureProcessor = m_scene->GetFeatureProcessor();
- Transform transform = transformServiceFeatureProcessor->GetTransformForId(m_objectId);
-
- ReflectionProbeFeatureProcessor::ReflectionProbeVector reflectionProbes;
- reflectionProbeFeatureProcessor->FindReflectionProbes(transform.GetTranslation(), reflectionProbes);
-
- if (!reflectionProbes.empty() && reflectionProbes[0])
- {
- m_shaderResourceGroup->SetConstant(modelToWorldConstantIndex, reflectionProbes[0]->GetTransform());
- m_shaderResourceGroup->SetConstant(modelToWorldInverseConstantIndex, Matrix3x4::CreateFromTransform(reflectionProbes[0]->GetTransform()).GetInverseFull());
- m_shaderResourceGroup->SetConstant(outerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetOuterObbWs().GetHalfLengths());
- m_shaderResourceGroup->SetConstant(innerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetInnerObbWs().GetHalfLengths());
- m_shaderResourceGroup->SetConstant(useReflectionProbeConstantIndex, true);
- m_shaderResourceGroup->SetConstant(useParallaxCorrectionConstantIndex, reflectionProbes[0]->GetUseParallaxCorrection());
-
- m_shaderResourceGroup->SetImage(reflectionCubeMapImageIndex, reflectionProbes[0]->GetCubeMapImage());
- }
- else
- {
- m_shaderResourceGroup->SetConstant(useReflectionProbeConstantIndex, false);
- }
- }
-
- m_shaderResourceGroup->Compile();
- m_objectSrgNeedsUpdate = false;
+ // Set m_objectSrgNeedsUpdate to false if there are object SRGs in the list
+ m_objectSrgNeedsUpdate = m_objectSrgNeedsUpdate && (m_objectSrgList.size() == 0);
}
- bool MeshDataInstance::MaterialRequiresForwardPassIblSpecular(Data::Instance material) const
+ bool ModelDataInstance::MaterialRequiresForwardPassIblSpecular(Data::Instance material) const
{
// look for a shader that has the o_materialUseForwardPassIBLSpecular option set
// Note: this should be changed to have the material automatically set the forwardPassIBLSpecular
@@ -1237,7 +1247,7 @@ namespace AZ
return false;
}
- void MeshDataInstance::SetVisible(bool isVisible)
+ void ModelDataInstance::SetVisible(bool isVisible)
{
m_visible = isVisible;
m_cullable.m_isHidden = !isVisible;
diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.cpp
index a9d8d5105f..c8e683e1d1 100644
--- a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.cpp
@@ -37,6 +37,11 @@ namespace AZ
m_currentTime = AZStd::chrono::system_clock::now();
}
+ void PostProcessFeatureProcessor::Deactivate()
+ {
+ m_viewAliasMap.clear();
+ }
+
void PostProcessFeatureProcessor::UpdateTime()
{
AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now();
@@ -45,6 +50,16 @@ namespace AZ
m_deltaTime = deltaTime.count();
}
+ void PostProcessFeatureProcessor::SetViewAlias(const AZ::RPI::ViewPtr sourceView, const AZ::RPI::ViewPtr targetView)
+ {
+ m_viewAliasMap[sourceView.get()] = targetView.get();
+ }
+
+ void PostProcessFeatureProcessor::RemoveViewAlias(const AZ::RPI::ViewPtr sourceView)
+ {
+ m_viewAliasMap.erase(sourceView.get());
+ }
+
void PostProcessFeatureProcessor::Simulate(const FeatureProcessor::SimulatePacket& packet)
{
AZ_PROFILE_SCOPE(RPI, "PostProcessFeatureProcessor: Simulate");
@@ -200,8 +215,12 @@ namespace AZ
AZ::Render::PostProcessSettings* PostProcessFeatureProcessor::GetLevelSettingsFromView(AZ::RPI::ViewPtr view)
{
+ // check for view aliases first
+ auto viewAliasiterator = m_viewAliasMap.find(view.get());
+
+ // Use the view alias if it exists
+ auto settingsIterator = m_blendedPerViewSettings.find(viewAliasiterator != m_viewAliasMap.end() ? viewAliasiterator->second : view.get());
// If no settings for the view is found, the global settings is returned.
- auto settingsIterator = m_blendedPerViewSettings.find(view.get());
return settingsIterator != m_blendedPerViewSettings.end()
? &settingsIterator->second
: m_globalAggregateLevelSettings.get();
diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.h
index 2c1cc98449..10af993d9d 100644
--- a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.h
+++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.h
@@ -34,6 +34,7 @@ namespace AZ
//! FeatureProcessor overrides...
void Activate() override;
+ void Deactivate() override;
void Simulate(const FeatureProcessor::SimulatePacket& packet) override;
//! PostProcessFeatureProcessorInterface...
@@ -43,6 +44,9 @@ namespace AZ
void OnPostProcessSettingsChanged() override;
PostProcessSettings* GetLevelSettingsFromView(AZ::RPI::ViewPtr view);
+ void SetViewAlias(const AZ::RPI::ViewPtr sourceView, const AZ::RPI::ViewPtr targetView);
+ void RemoveViewAlias(const AZ::RPI::ViewPtr sourceView);
+
private:
PostProcessFeatureProcessor(const PostProcessFeatureProcessor&) = delete;
@@ -83,6 +87,8 @@ namespace AZ
// Each camera/view will have its own PostProcessSettings
AZStd::unordered_map m_blendedPerViewSettings;
+ // This is used for mimicking a postfx setting of a different view
+ AZStd::unordered_map m_viewAliasMap;
};
} // namespace Render
} // namespace AZ
diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/EyeAdaptationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/EyeAdaptationPass.cpp
index 862892ad1b..5683241693 100644
--- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/EyeAdaptationPass.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/EyeAdaptationPass.cpp
@@ -81,7 +81,7 @@ namespace AZ
if (scene)
{
PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor();
- AZ::RPI::ViewPtr view = GetView();
+ AZ::RPI::ViewPtr view = GetRenderPipeline()->GetDefaultView();
if (fp)
{
PostProcessSettings* postProcessSettings = fp->GetLevelSettingsFromView(view);
@@ -110,7 +110,7 @@ namespace AZ
PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor();
if (fp)
{
- AZ::RPI::ViewPtr view = GetView();
+ AZ::RPI::ViewPtr view = GetRenderPipeline()->GetDefaultView();
PostProcessSettings* postProcessSettings = fp->GetLevelSettingsFromView(view);
if (postProcessSettings)
{
diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp
index e86d91d387..4ac5782b04 100644
--- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp
@@ -120,15 +120,17 @@ namespace AZ
m_scene->RemoveRenderPipeline(m_environmentCubeMapPipelineId);
m_environmentCubeMapPass = nullptr;
- // restore exposure
- sceneSrg->SetConstant(m_iblExposureConstantIndex, m_previousExposure);
+ // restore exposures
+ sceneSrg->SetConstant(m_globalIblExposureConstantIndex, m_previousGlobalIblExposure);
+ sceneSrg->SetConstant(m_skyBoxExposureConstantIndex, m_previousSkyBoxExposure);
m_buildingCubeMap = false;
}
else
{
- // set exposure to 0.0 while baking the cubemap
- sceneSrg->SetConstant(m_iblExposureConstantIndex, 0.0f);
+ // set exposures to the user specified value while baking the cubemap
+ sceneSrg->SetConstant(m_globalIblExposureConstantIndex, m_bakeExposure);
+ sceneSrg->SetConstant(m_skyBoxExposureConstantIndex, m_bakeExposure);
}
}
@@ -162,6 +164,7 @@ namespace AZ
m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_outerObbHalfLengthsRenderConstantIndex, m_outerObbWs.GetHalfLengths());
m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_innerObbHalfLengthsRenderConstantIndex, m_innerObbWs.GetHalfLengths());
m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_useParallaxCorrectionRenderConstantIndex, m_useParallaxCorrection);
+ m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_exposureConstantIndex, m_renderExposure);
m_renderOuterSrg->SetImage(m_reflectionRenderData->m_reflectionCubeMapRenderImageIndex, m_cubeMapImage);
m_renderOuterSrg->Compile();
@@ -172,6 +175,7 @@ namespace AZ
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerObbHalfLengthsRenderConstantIndex, m_outerObbWs.GetHalfLengths());
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_innerObbHalfLengthsRenderConstantIndex, m_innerObbWs.GetHalfLengths());
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_useParallaxCorrectionRenderConstantIndex, m_useParallaxCorrection);
+ m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_exposureConstantIndex, m_renderExposure);
m_renderInnerSrg->SetImage(m_reflectionRenderData->m_reflectionCubeMapRenderImageIndex, m_cubeMapImage);
m_renderInnerSrg->Compile();
@@ -303,9 +307,10 @@ namespace AZ
const RPI::Ptr& rootPass = environmentCubeMapPipeline->GetRootPass();
rootPass->AddChild(m_environmentCubeMapPass);
- // store the current IBL exposure value
+ // store the current IBL exposure values
Data::Instance sceneSrg = m_scene->GetShaderResourceGroup();
- m_previousExposure = sceneSrg->GetConstant(m_iblExposureConstantIndex);
+ m_previousGlobalIblExposure = sceneSrg->GetConstant(m_globalIblExposureConstantIndex);
+ m_previousSkyBoxExposure = sceneSrg->GetConstant(m_skyBoxExposureConstantIndex);
m_scene->AddRenderPipeline(environmentCubeMapPipeline);
}
@@ -326,6 +331,17 @@ namespace AZ
m_meshFeatureProcessor->SetVisible(m_visualizationMeshHandle, showVisualization);
}
+ void ReflectionProbe::SetRenderExposure(float renderExposure)
+ {
+ m_renderExposure = renderExposure;
+ m_updateSrg = true;
+ }
+
+ void ReflectionProbe::SetBakeExposure(float bakeExposure)
+ {
+ m_bakeExposure = bakeExposure;
+ }
+
const RHI::DrawPacket* ReflectionProbe::BuildDrawPacket(
const Data::Instance& srg,
const RPI::Ptr& pipelineState,
diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h
index bee304c5b9..17ef54367b 100644
--- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h
+++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h
@@ -61,6 +61,7 @@ namespace AZ
RHI::ShaderInputNameIndex m_outerObbHalfLengthsRenderConstantIndex = "m_outerObbHalfLengths";
RHI::ShaderInputNameIndex m_innerObbHalfLengthsRenderConstantIndex = "m_innerObbHalfLengths";
RHI::ShaderInputNameIndex m_useParallaxCorrectionRenderConstantIndex = "m_useParallaxCorrection";
+ RHI::ShaderInputNameIndex m_exposureConstantIndex = "m_exposure";
RHI::ShaderInputNameIndex m_reflectionCubeMapRenderImageIndex = "m_reflectionCubeMap";
};
@@ -106,6 +107,14 @@ namespace AZ
// enables or disables rendering of the visualization sphere
void ShowVisualization(bool showVisualization);
+ // the exposure to use when rendering meshes with this probe's cubemap
+ void SetRenderExposure(float renderExposure);
+ float GetRenderExposure() const { return m_renderExposure; }
+
+ // the exposure to use when baking the probe cubemap
+ void SetBakeExposure(float bakeExposure);
+ float GetBakeExposure() const { return m_bakeExposure; }
+
private:
AZ_DISABLE_COPY_MOVE(ReflectionProbe);
@@ -157,6 +166,8 @@ namespace AZ
RHI::ConstPtr m_blendWeightDrawPacket;
RHI::ConstPtr m_renderOuterDrawPacket;
RHI::ConstPtr m_renderInnerDrawPacket;
+ float m_renderExposure = 0.0f;
+ float m_bakeExposure = 0.0f;
bool m_updateSrg = false;
const RHI::DrawItemSortKey InvalidSortKey = static_cast(-1);
@@ -169,8 +180,10 @@ namespace AZ
RPI::Ptr m_environmentCubeMapPass = nullptr;
RPI::RenderPipelineId m_environmentCubeMapPipelineId;
BuildCubeMapCallback m_callback;
- RHI::ShaderInputNameIndex m_iblExposureConstantIndex = "m_iblExposure";
- float m_previousExposure = 0.0f;
+ RHI::ShaderInputNameIndex m_globalIblExposureConstantIndex = "m_iblExposure";
+ RHI::ShaderInputNameIndex m_skyBoxExposureConstantIndex = "m_cubemapExposure";
+ float m_previousGlobalIblExposure = 0.0f;
+ float m_previousSkyBoxExposure = 0.0f;
bool m_buildingCubeMap = false;
};
diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp
index ae63ff1dde..e9038858ad 100644
--- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp
@@ -283,6 +283,18 @@ namespace AZ
probe->ShowVisualization(showVisualization);
}
+ void ReflectionProbeFeatureProcessor::SetRenderExposure(const ReflectionProbeHandle& probe, float renderExposure)
+ {
+ AZ_Assert(probe.get(), "SetRenderExposure called with an invalid handle");
+ probe->SetRenderExposure(renderExposure);
+ }
+
+ void ReflectionProbeFeatureProcessor::SetBakeExposure(const ReflectionProbeHandle& probe, float bakeExposure)
+ {
+ AZ_Assert(probe.get(), "SetBakeExposure called with an invalid handle");
+ probe->SetBakeExposure(bakeExposure);
+ }
+
void ReflectionProbeFeatureProcessor::FindReflectionProbes(const Vector3& position, ReflectionProbeVector& reflectionProbes)
{
reflectionProbes.clear();
diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp
index 4c379c4239..c135b017fa 100644
--- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp
@@ -95,13 +95,13 @@ namespace AZ
renderProxy.m_instance->m_model->WaitForUpload();
}
- //Note: we are creating pointers to the meshDataInstance cullpacket and lod packet here,
+ //Note: we are creating pointers to the modelDataInstance cullpacket and lod packet here,
//and holding them until the skinnedMeshDispatchItems are dispatched. There is an assumption that the underlying
//data will not move during this phase.
- MeshDataInstance& meshDataInstance = **renderProxy.m_meshHandle;
- m_workgroup.m_cullPackets.push_back(&meshDataInstance.GetCullPacket());
- m_workgroup.m_drawListMask |= meshDataInstance.GetCullPacket().m_drawListMask;
- m_lodPackets.push_back(&meshDataInstance.GetLodPacket());
+ ModelDataInstance& modelDataInstance = **renderProxy.m_meshHandle;
+ m_workgroup.m_cullPackets.push_back(&modelDataInstance.GetCullPacket());
+ m_workgroup.m_drawListMask |= modelDataInstance.GetCullPacket().m_drawListMask;
+ m_lodPackets.push_back(&modelDataInstance.GetLodPacket());
m_potentiallyVisibleProxies.push_back(&renderProxy);
}
}
@@ -187,8 +187,8 @@ namespace AZ
renderProxy.m_instance->m_model->WaitForUpload();
}
- MeshDataInstance& meshDataInstance = **renderProxy.m_meshHandle;
- const RPI::Cullable& cullable = meshDataInstance.GetCullable();
+ ModelDataInstance& modelDataInstance = **renderProxy.m_meshHandle;
+ const RPI::Cullable& cullable = modelDataInstance.GetCullable();
for (const RPI::ViewPtr& viewPtr : packet.m_views)
{
diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h
index 97ac3baa90..abad1fb263 100644
--- a/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h
+++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h
@@ -75,6 +75,9 @@ namespace AZ
//! Return True if the swap chain prefers exclusive full screen mode and a transition happened, false otherwise.
virtual bool SetExclusiveFullScreenState([[maybe_unused]]bool fullScreenState) { return false; }
+ //! Recreate the swapchain if it becomes invalid during presenting. This should happen at the end of the frame
+ //! due to images being used as attachments in the frame graph.
+ virtual void ProcessRecreation() {};
protected:
SwapChain();
@@ -98,6 +101,14 @@ namespace AZ
//////////////////////////////////////////////////////////////////////////
+ //! Shutdown and clear all the images.
+ void ShutdownImages();
+
+ //! Initialized all the images.
+ ResultCode InitImages();
+
+ //! Flag indicating if swapchain recreation is needed at the end of the frame.
+ bool m_pendingRecreation = false;
private:
bool ValidateDescriptor(const SwapChainDescriptor& descriptor) const;
diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphAttachmentDatabase.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphAttachmentDatabase.cpp
index 6bac2b8c7d..388277ff59 100644
--- a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphAttachmentDatabase.cpp
+++ b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphAttachmentDatabase.cpp
@@ -134,7 +134,6 @@ namespace AZ
m_scopeAttachmentLookup.clear();
m_imageAttachments.clear();
m_bufferAttachments.clear();
- m_swapChainAttachments.clear();
m_importedImageAttachments.clear();
m_importedBufferAttachments.clear();
m_transientImageAttachments.clear();
@@ -153,6 +152,13 @@ namespace AZ
delete attachment;
}
m_attachments.clear();
+
+ for (auto swapchainAttachment : m_swapChainAttachments)
+ {
+ swapchainAttachment->GetSwapChain()->ProcessRecreation();
+ }
+
+ m_swapChainAttachments.clear();
}
ImageDescriptor FrameGraphAttachmentDatabase::GetImageDescriptor(const AttachmentId& attachmentId) const
diff --git a/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp
index ff1f0e69a6..074eedf1b6 100644
--- a/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp
+++ b/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp
@@ -58,43 +58,68 @@ namespace AZ
// Overwrite descriptor dimensions with the native ones (the ones assigned by the platform) returned by InitInternal.
m_descriptor.m_dimensions = nativeDimensions;
- m_images.reserve(m_descriptor.m_dimensions.m_imageCount);
+ resultCode = InitImages();
+ }
- for (uint32_t imageIdx = 0; imageIdx < m_descriptor.m_dimensions.m_imageCount; ++imageIdx)
- {
- m_images.emplace_back(RHI::Factory::Get().CreateImage());
- }
+ return resultCode;
+ }
- InitImageRequest request;
+ void SwapChain::ShutdownImages()
+ {
+ // Shutdown existing set of images.
+ uint32_t imageSize = aznumeric_cast(m_images.size());
+ for (uint32_t imageIdx = 0; imageIdx < imageSize; ++imageIdx)
+ {
+ m_images[imageIdx]->Shutdown();
+ }
- RHI::ImageDescriptor& imageDescriptor = request.m_descriptor;
- imageDescriptor.m_dimension = RHI::ImageDimension::Image2D;
- imageDescriptor.m_bindFlags = RHI::ImageBindFlags::Color;
- imageDescriptor.m_size.m_width = m_descriptor.m_dimensions.m_imageWidth;
- imageDescriptor.m_size.m_height = m_descriptor.m_dimensions.m_imageHeight;
- imageDescriptor.m_format = m_descriptor.m_dimensions.m_imageFormat;
+ m_images.clear();
+ }
- for (uint32_t imageIdx = 0; imageIdx < m_descriptor.m_dimensions.m_imageCount; ++imageIdx)
- {
- request.m_image = m_images[imageIdx].get();
- request.m_imageIndex = imageIdx;
+ ResultCode SwapChain::InitImages()
+ {
+ ResultCode resultCode = ResultCode::Success;
- resultCode = ImagePoolBase::InitImage(
- request.m_image,
- imageDescriptor,
- [this, &request]()
+ m_images.reserve(m_descriptor.m_dimensions.m_imageCount);
+
+ // If the new display mode has more buffers, add them.
+ for (uint32_t i = 0; i < m_descriptor.m_dimensions.m_imageCount; ++i)
+ {
+ m_images.emplace_back(RHI::Factory::Get().CreateImage());
+ }
+
+ InitImageRequest request;
+
+ RHI::ImageDescriptor& imageDescriptor = request.m_descriptor;
+ imageDescriptor.m_dimension = RHI::ImageDimension::Image2D;
+ imageDescriptor.m_bindFlags = RHI::ImageBindFlags::Color;
+ imageDescriptor.m_size.m_width = m_descriptor.m_dimensions.m_imageWidth;
+ imageDescriptor.m_size.m_height = m_descriptor.m_dimensions.m_imageHeight;
+ imageDescriptor.m_format = m_descriptor.m_dimensions.m_imageFormat;
+
+ for (uint32_t imageIdx = 0; imageIdx < m_descriptor.m_dimensions.m_imageCount; ++imageIdx)
+ {
+ request.m_image = m_images[imageIdx].get();
+ request.m_imageIndex = imageIdx;
+
+ resultCode = ImagePoolBase::InitImage(
+ request.m_image, imageDescriptor,
+ [this, &request]()
{
return InitImageInternal(request);
});
- if (resultCode != ResultCode::Success)
- {
- Shutdown();
- break;
- }
+ if (resultCode != ResultCode::Success)
+ {
+ AZ_Error("Swapchain", false, "Failed to initialize images.");
+ Shutdown();
+ break;
}
}
+ // Reset the current index back to 0 so we match the platform swap chain.
+ m_currentImageIndex = 0;
+
return resultCode;
}
@@ -105,63 +130,15 @@ namespace AZ
}
ResultCode SwapChain::Resize(const RHI::SwapChainDimensions& dimensions)
- {
- // Shutdown existing set of images.
- for (uint32_t imageIdx = 0; imageIdx < GetImageCount(); ++imageIdx)
- {
- m_images[imageIdx]->Shutdown();
- }
+ {
+ ShutdownImages();
SwapChainDimensions nativeDimensions = dimensions;
ResultCode resultCode = ResizeInternal(dimensions, &nativeDimensions);
if (resultCode == ResultCode::Success)
{
m_descriptor.m_dimensions = nativeDimensions;
- m_images.reserve(m_descriptor.m_dimensions.m_imageCount);
-
- // If the new display mode has more buffers, add them.
- while (m_images.size() < static_cast(m_descriptor.m_dimensions.m_imageCount))
- {
- m_images.emplace_back(RHI::Factory::Get().CreateImage());
- }
-
- // If it has fewer, trim down.
- while (m_images.size() > static_cast(m_descriptor.m_dimensions.m_imageCount))
- {
- m_images.pop_back();
- }
-
- InitImageRequest request;
-
- RHI::ImageDescriptor& imageDescriptor = request.m_descriptor;
- imageDescriptor.m_dimension = RHI::ImageDimension::Image2D;
- imageDescriptor.m_bindFlags = RHI::ImageBindFlags::Color;
- imageDescriptor.m_size.m_width = m_descriptor.m_dimensions.m_imageWidth;
- imageDescriptor.m_size.m_height = m_descriptor.m_dimensions.m_imageHeight;
- imageDescriptor.m_format = m_descriptor.m_dimensions.m_imageFormat;
-
- for (uint32_t imageIdx = 0; imageIdx < GetImageCount(); ++imageIdx)
- {
- request.m_image = m_images[imageIdx].get();
- request.m_imageIndex = imageIdx;
-
- resultCode = ImagePoolBase::InitImage(
- request.m_image,
- imageDescriptor,
- [this, &request]()
- {
- return InitImageInternal(request);
- });
-
- if (resultCode != ResultCode::Success)
- {
- Shutdown();
- break;
- }
- }
-
- // Reset the current index back to 0 so we match the platform swap chain.
- m_currentImageIndex = 0;
+ resultCode = InitImages();
}
return resultCode;
@@ -188,7 +165,7 @@ namespace AZ
uint32_t SwapChain::GetImageCount() const
{
- return static_cast(m_images.size());
+ return aznumeric_cast(m_images.size());
}
uint32_t SwapChain::GetCurrentImageIndex() const
@@ -209,8 +186,18 @@ namespace AZ
void SwapChain::Present()
{
AZ_TRACE_METHOD();
- m_currentImageIndex = PresentInternal();
- AZ_Assert(m_currentImageIndex < m_images.size(), "Invalid image index");
+ // Due to swapchain recreation, the images are refreshed.
+ // There is no need to present swapchain for this frame.
+ const uint32_t imageCount = aznumeric_cast(m_images.size());
+ if (imageCount == 0)
+ {
+ return;
+ }
+ else
+ {
+ m_currentImageIndex = PresentInternal();
+ AZ_Assert(m_currentImageIndex < imageCount, "Invalid image index");
+ }
}
}
}
diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp
index bef2b154e1..47c92d97fb 100644
--- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp
+++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp
@@ -59,14 +59,26 @@ namespace AZ
m_swapChainBarrier.m_isValid = true;
}
+ void SwapChain::ProcessRecreation()
+ {
+ if (m_pendingRecreation)
+ {
+ ShutdownImages();
+ InvalidateNativeSwapChain();
+ CreateSwapchain();
+ InitImages();
+
+ m_pendingRecreation = false;
+ }
+ }
+
void SwapChain::SetVerticalSyncIntervalInternal(uint32_t previousVsyncInterval)
{
if (GetDescriptor().m_verticalSyncInterval == 0 || previousVsyncInterval == 0)
{
// The presentation mode may change when transitioning to or from a vsynced presentation mode
// In this case, the swapchain must be recreated.
- InvalidateNativeSwapChain();
- CreateSwapchain();
+ m_pendingRecreation = true;
}
}
@@ -231,8 +243,7 @@ namespace AZ
// VK_SUBOPTIMAL_KHR is treated as success, but we better update the surface info as well.
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
{
- InvalidateNativeSwapChain();
- CreateSwapchain();
+ m_pendingRecreation = true;
}
else
{
@@ -246,18 +257,16 @@ namespace AZ
}
};
- m_presentationQueue->QueueCommand(AZStd::move(presentCommand));
-
uint32_t acquiredImageIndex = GetCurrentImageIndex();
RHI::ResultCode result = AcquireNewImage(&acquiredImageIndex);
if (result == RHI::ResultCode::Fail)
{
- InvalidateNativeSwapChain();
- CreateSwapchain();
+ m_pendingRecreation = true;
return 0;
}
else
{
+ m_presentationQueue->QueueCommand(AZStd::move(presentCommand));
return acquiredImageIndex;
}
}
diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.h
index ee2ff3c207..68abc97b2d 100644
--- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.h
+++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.h
@@ -51,6 +51,7 @@ namespace AZ
void QueueBarrier(const VkPipelineStageFlags src, const VkPipelineStageFlags dst, const VkImageMemoryBarrier& imageBarrier);
+ void ProcessRecreation() override;
private:
SwapChain() = default;
diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h
index c42991725e..b93458113b 100644
--- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h
+++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h
@@ -56,8 +56,8 @@ namespace AZ
OwnerRenderPipeline = AZ_BIT(5)
};
- void SetOwenrScene(const Scene* scene);
- void SetOwenrRenderPipeline(const RenderPipeline* renderPipeline);
+ void SetOwnerScene(const Scene* scene);
+ void SetOwnerRenderPipeline(const RenderPipeline* renderPipeline);
void SetPassName(Name passName);
void SetTemplateName(Name passTemplateName);
void SetPassClass(TypeId passClassTypeId);
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp
index 9fc99e3ea4..dbf0fea791 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp
@@ -2088,7 +2088,7 @@ namespace AZ
AZ::Vector3 vpos; //note: it seems to be fastest to reuse a local Vector3 rather than constructing new ones each loop iteration
for (uint32_t i = 0; i < elementCount; ++i)
{
- vpos.Set(const_cast(reinterpret_cast(&buffer[i])));
+ vpos.Set(reinterpret_cast(&buffer[i]));
aabb.AddPoint(vpos);
}
}
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassFilter.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassFilter.cpp
index d9e458c615..d172abd81f 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassFilter.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassFilter.cpp
@@ -90,13 +90,13 @@ namespace AZ
return filter;
}
- void PassFilter::SetOwenrScene(const Scene* scene)
+ void PassFilter::SetOwnerScene(const Scene* scene)
{
m_ownerScene = scene;
UpdateFilterOptions();
}
- void PassFilter::SetOwenrRenderPipeline(const RenderPipeline* renderPipeline)
+ void PassFilter::SetOwnerRenderPipeline(const RenderPipeline* renderPipeline)
{
m_ownerRenderPipeline = renderPipeline;
UpdateFilterOptions();
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp
index 9a432643d7..e362229d2d 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp
@@ -201,23 +201,11 @@ namespace AZ
AZ::Vector3& normal) const
{
const BufferAssetView& indexBufferView = mesh.GetIndexBufferAssetView();
- const AZStd::array_view& streamBufferList = mesh.GetStreamBufferInfoList();
+ const BufferAssetView* positionBufferView = mesh.GetSemanticBufferAssetView(m_positionName);
- // find position semantic
- const ModelLodAsset::Mesh::StreamBufferInfo* positionBuffer = nullptr;
-
- for (const ModelLodAsset::Mesh::StreamBufferInfo& bufferInfo : streamBufferList)
+ if (positionBufferView && positionBufferView->GetBufferAsset().Get())
{
- if (bufferInfo.m_semantic.m_name == m_positionName)
- {
- positionBuffer = &bufferInfo;
- break;
- }
- }
-
- if (positionBuffer && positionBuffer->m_bufferAssetView.GetBufferAsset().Get())
- {
- BufferAsset* bufferAssetViewPtr = positionBuffer->m_bufferAssetView.GetBufferAsset().Get();
+ BufferAsset* bufferAssetViewPtr = positionBufferView->GetBufferAsset().Get();
BufferAsset* indexAssetViewPtr = indexBufferView.GetBufferAsset().Get();
if (!bufferAssetViewPtr || !indexAssetViewPtr)
@@ -225,7 +213,7 @@ namespace AZ
return false;
}
- RHI::BufferViewDescriptor positionBufferViewDesc = bufferAssetViewPtr->GetBufferViewDescriptor();
+ RHI::BufferViewDescriptor positionBufferViewDesc = positionBufferView->GetBufferViewDescriptor();
AZStd::array_view positionRawBuffer = bufferAssetViewPtr->GetBuffer();
const uint32_t positionElementSize = positionBufferViewDesc.m_elementSize;
@@ -234,22 +222,28 @@ namespace AZ
// Position is 3 floats
if (positionElementSize != sizeof(float) * 3)
{
- AZ_Warning("ModelAsset", false, "unsupported mesh posiiton format, only full 3 floats per vertex are supported at the moment");
+ AZ_Warning(
+ "ModelAsset", false, "unsupported mesh posiiton format, only full 3 floats per vertex are supported at the moment");
return false;
}
+ RHI::BufferViewDescriptor indexBufferViewDesc = indexBufferView.GetBufferViewDescriptor();
AZStd::array_view indexRawBuffer = indexAssetViewPtr->GetBuffer();
- RHI::BufferViewDescriptor indexRawDesc = indexAssetViewPtr->GetBufferViewDescriptor();
-
- bool anyHit = false;
const AZ::Vector3 rayEnd = rayStart + rayDir;
AZ::Vector3 a, b, c;
AZ::Vector3 intersectionNormal;
+ bool anyHit = false;
float shortestDistanceNormalized = AZStd::numeric_limits::max();
- const AZ::u32* indexPtr = reinterpret_cast(indexRawBuffer.data());
- for (uint32_t indexIter = 0; indexIter <= indexRawDesc.m_elementCount - 3; indexIter += 3, indexPtr += 3)
+
+ const AZ::u32* indexPtr = reinterpret_cast(
+ indexRawBuffer.data() + (indexBufferViewDesc.m_elementOffset * indexBufferViewDesc.m_elementSize));
+ const float* positionPtr = reinterpret_cast(
+ positionRawBuffer.data() + (positionBufferViewDesc.m_elementOffset * positionBufferViewDesc.m_elementSize));
+
+ constexpr int StepSize = 3; // number of values per vertex (x, y, z)
+ for (uint32_t indexIter = 0; indexIter < indexBufferViewDesc.m_elementCount; indexIter += StepSize, indexPtr += StepSize)
{
AZ::u32 index0 = indexPtr[0];
AZ::u32 index1 = indexPtr[1];
@@ -261,17 +255,17 @@ namespace AZ
return false;
}
- const float* p = reinterpret_cast(&positionRawBuffer[index0 * positionElementSize]);
- a.Set(const_cast(p)); // faster than AZ::Vector3 c-tor
-
- p = reinterpret_cast(&positionRawBuffer[index1 * positionElementSize]);
- b.Set(const_cast(p));
-
- p = reinterpret_cast(&positionRawBuffer[index2 * positionElementSize]);
- c.Set(const_cast(p));
+ // faster than AZ::Vector3 c-tor
+ const float* aRef = &positionPtr[index0 * StepSize];
+ a.Set(aRef);
+ const float* bRef = &positionPtr[index1 * StepSize];
+ b.Set(bRef);
+ const float* cRef = &positionPtr[index2 * StepSize];
+ c.Set(cRef);
float currentDistanceNormalized;
- if (AZ::Intersect::IntersectSegmentTriangleCCW(rayStart, rayEnd, a, b, c, intersectionNormal, currentDistanceNormalized))
+ if (AZ::Intersect::IntersectSegmentTriangleCCW(
+ rayStart, rayEnd, a, b, c, intersectionNormal, currentDistanceNormalized))
{
anyHit = true;
diff --git a/Gems/Atom/RPI/Code/Tests.Builders/BuilderTestFixture.h b/Gems/Atom/RPI/Code/Tests.Builders/BuilderTestFixture.h
index 31c1bc6715..02e69e732c 100644
--- a/Gems/Atom/RPI/Code/Tests.Builders/BuilderTestFixture.h
+++ b/Gems/Atom/RPI/Code/Tests.Builders/BuilderTestFixture.h
@@ -46,7 +46,6 @@ namespace UnitTest
bool DeleteEntity(const AZ::EntityId&) override { return false; }
AZ::Entity* FindEntity(const AZ::EntityId&) override { return nullptr; }
AZ::BehaviorContext* GetBehaviorContext() override { return nullptr; }
- const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
diff --git a/Gems/Atom/RPI/Code/Tests/Common/AssetManagerTestFixture.h b/Gems/Atom/RPI/Code/Tests/Common/AssetManagerTestFixture.h
index ee3ad94d4f..fb88e62617 100644
--- a/Gems/Atom/RPI/Code/Tests/Common/AssetManagerTestFixture.h
+++ b/Gems/Atom/RPI/Code/Tests/Common/AssetManagerTestFixture.h
@@ -44,7 +44,6 @@ namespace UnitTest
AZ::Entity* FindEntity(const AZ::EntityId&) override { return nullptr; }
AZ::BehaviorContext* GetBehaviorContext() override { return nullptr; }
AZ::JsonRegistrationContext* GetJsonRegistrationContext() override { return nullptr; }
- const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
diff --git a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp
index 7b07e14de0..81d773d8c0 100644
--- a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp
+++ b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp
@@ -38,7 +38,7 @@ namespace UnitTest
bufferData.resize(bufferSize);
//The actual data doesn't matter
- const uint8_t bufferDataSize = static_cast(bufferData.size());
+ const uint8_t bufferDataSize = aznumeric_cast(bufferData.size());
for (uint8_t i = 0; i < bufferDataSize; ++i)
{
bufferData[i] = i;
@@ -248,7 +248,8 @@ namespace UnitTest
return asset;
}
- AZ::Data::Asset BuildTestModel(const uint32_t lodCount, const uint32_t sharedMeshCount, const uint32_t separateMeshCount, ExpectedModel& expectedModel)
+ AZ::Data::Asset