Merge remote-tracking branch 'upstream/stabilization/2110' into nvsickle/StabToDevNov21

Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
monroegm-disable-blank-issue-2
Nicholas Van Sickle 4 years ago
commit 8d5dd4e35f

@ -62164,7 +62164,7 @@ An Entity can be selected by using the pick button, or by dragging an Entity fro
<message id="HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_NAME">
<source>HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_NAME</source>
<comment>Simple Type: EntityID C++ Type: const EntityId&amp;</comment>
<translation type="unfinished">Entity</translation>
<translation type="unfinished">EntityID</translation>
</message>
<message id="HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_TOOLTIP">
<source>HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_TOOLTIP</source>
@ -62202,7 +62202,7 @@ An Entity can be selected by using the pick button, or by dragging an Entity fro
<message id="HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_NAME">
<source>HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_NAME</source>
<comment>Simple Type: EntityID C++ Type: const EntityId&amp;</comment>
<translation type="unfinished">Entity</translation>
<translation type="unfinished">EntityId</translation>
</message>
<message id="HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_TOOLTIP">
<source>HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_TOOLTIP</source>
@ -81852,7 +81852,7 @@ The element is removed from its current parent and added as a child of the new p
<message id="HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_NAME">
<source>HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_NAME</source>
<comment>Simple Type: EntityID C++ Type: const EntityId&amp;</comment>
<translation type="unfinished">Entity</translation>
<translation type="unfinished">EntityID</translation>
</message>
<message id="HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_TOOLTIP">
<source>HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_TOOLTIP</source>
@ -89198,7 +89198,7 @@ The element is removed from its current parent and added as a child of the new p
<message id="HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_NAME">
<source>HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_NAME</source>
<comment>Simple Type: EntityID C++ Type: const EntityId&amp;</comment>
<translation type="unfinished">Entity</translation>
<translation type="unfinished">EntityID</translation>
</message>
<message id="HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_TOOLTIP">
<source>HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_TOOLTIP</source>
@ -89236,7 +89236,7 @@ The element is removed from its current parent and added as a child of the new p
<message id="HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_NAME">
<source>HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_NAME</source>
<comment>Simple Type: EntityID C++ Type: const EntityId&amp;</comment>
<translation type="unfinished">Entity</translation>
<translation type="unfinished">EntityID</translation>
</message>
<message id="HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_TOOLTIP">
<source>HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_TOOLTIP</source>

@ -145,7 +145,7 @@
<Class name="float" field="ProjectorNearPlane" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}" value="0.0000000" specializationTypeId="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
<Class name="AzFramework::SimpleAssetReference&lt;LmbrCentral::TextureAsset&gt;" field="ProjectorTexture" type="{68E92460-5C0C-4031-9620-6F1A08763243}" version="1" specializationTypeId="{68E92460-5C0C-4031-9620-6F1A08763243}">
<Class name="SimpleAssetReferenceBase" field="BaseClass1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}" version="1" specializationTypeId="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
<Class name="AZStd::string" field="AssetPath" type="{EF8FF807-DDEE-4EB0-B678-4CA3A2C490A4}" value="engineassets/textures/defaults/spot_default.dds" specializationTypeId="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="AZStd::string" field="AssetPath" type="{EF8FF807-DDEE-4EB0-B678-4CA3A2C490A4}" value="" specializationTypeId="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</Class>
<Class name="AzFramework::SimpleAssetReference&lt;LmbrCentral::MaterialAsset&gt;" field="ProjectorMaterial" type="{B7B8ECC7-FF89-4A76-A50E-4C6CA2B6E6B4}" version="1" specializationTypeId="{B7B8ECC7-FF89-4A76-A50E-4C6CA2B6E6B4}">

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cf441215a769562f88aa20711aee68dadcbf02597d1e2270547055e8e6aec6a3
size 77

@ -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",
},
}

@ -54,6 +54,7 @@ set(ENABLED_GEMS
AWSMetrics
PrefabBuilder
AudioSystem
Terrain
Profiler
Multiplayer
)

@ -56,6 +56,9 @@ add_subdirectory(streaming)
## Smoke ##
add_subdirectory(smoke)
## Terrain ##
add_subdirectory(Terrain)
## AWS ##
add_subdirectory(AWS)

@ -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()

@ -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)

@ -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

@ -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
"""

@ -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)

@ -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"]
)

@ -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"])

@ -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<int>(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());
}

@ -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

@ -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");
}

@ -131,7 +131,6 @@ public:
enum EAttachmentType
{
eAT_Pivot,
eAT_GeomCacheNode,
eAT_CharacterBone,
};

@ -608,7 +608,7 @@ bool CObjectManager::AddObject(CBaseObject* obj)
if (CEntityObject* entityObj = qobject_cast<CEntityObject*>(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);
}

@ -13,6 +13,7 @@
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/View.h>
#include <Atom/RPI.Reflect/System/RenderPipelineDescriptor.h>
#include <PostProcess/PostProcessFeatureProcessor.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/MatrixUtils.h>
#include <AzCore/Name/Name.h>
@ -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<AZ::Render::PostProcessFeatureProcessor>())
{
// 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<AZ::Render::PostProcessFeatureProcessor>())
{
// 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<AZ::Render::PostProcessFeatureProcessor>())
{
fp->SetViewAlias(m_view, targetView);
m_targetView = targetView;
}
}
}
m_view->SetCameraTransform(cameraTransform);
m_view->SetViewToClipMatrix(cameraProjection);
}

@ -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<AZStd::string> m_passHierarchy; //!< Pass hierarchy (includes pipelineName and CopyToSwapChain).
CaptureFinishedCallback m_captureFinishedCallback; //!< Stored callback called from OnCaptureFinished.

@ -16,6 +16,7 @@
#include <AzCore/Component/ComponentApplication.h>
#include <AzFramework/Windowing/WindowBus.h>
#include <Atom/RPI.Public/ViewProviderBus.h>
// Qt
#include <QAction>
@ -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<float>(width), static_cast<float>(height)));
TrackView::ProjectionFromCameraEntityId(activeCameraEntityId, aznumeric_cast<float>(width), aznumeric_cast<float>(height)),
view);
}
CSequenceBatchRenderDialog::CSequenceBatchRenderDialog(float fps, QWidget* pParent /* = nullptr */)

@ -23,9 +23,9 @@
// AzCore
#include <AzCore/Component/TickBus.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Utils/Utils.h>
// AzFramework
#include <AzFramework/API/ApplicationAPI.h>
// AzQtComponents
#include <AzQtComponents/Utilities/DesktopUtilities.h>
@ -54,92 +54,14 @@
#include <Shellapi.h>
#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)

@ -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);

@ -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);

@ -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

@ -14,7 +14,6 @@
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Utils/Utils.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h> // for ebus events
#include <AzFramework/API/ApplicationAPI.h>
#include <AzCore/std/string/conversions.h>
#include <AzFramework/IO/LocalFileIO.h>
@ -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<int>(engineRoot.size()));
}
//////////////////////////////////////////////////////////////////////////

@ -25,8 +25,6 @@
#include <AzCore/Utils/Utils.h>
// AzFramework
#include <AzFramework/API/ApplicationAPI.h>
// AzToolsFramework
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
@ -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);

@ -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<JsonRegistrationContext>() : 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<AZ::StringFunc::Path::FixedString> 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

@ -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<typename Iterator>
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;

@ -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;

@ -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;

@ -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]);
}

@ -50,7 +50,12 @@ namespace AZ
if (!s_instance)
{
s_instance = Environment::FindVariable<NameDictionary>(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<NameDictionary>(NameDictionaryInstanceName, true, false);
}
return s_instance.IsConstructed();

@ -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());
}

@ -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;
// Strip out any trailing path separators
AZ::StringFunc::Strip(normalized, AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING AZ_WRONG_FILESYSTEM_SEPARATOR_STRING,false, false, true);
// Lower case always
AZStd::to_lower(normalized.begin(), normalized.end());
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<char>(std::tolower(element));
};
// Substitute path separators with '_'
AZStd::replace(normalized.begin(), normalized.end(), '\\', '_');
AZStd::replace(normalized.begin(), normalized.end(), '/', '_');
// 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));
// 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<AZ::u32>(branchTokenCrc));
token = AZStd::string(branchToken);
// Perform the CRC32 calculation
constexpr bool forceLowercase = true;
return static_cast<AZ::u32>(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));
}
}

@ -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);
}
//////////////////////////////////////////////////////////////////////////

@ -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&));

@ -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 {}

@ -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

@ -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 {}

@ -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; }

@ -69,6 +69,7 @@
#include <AzCore/Console/Console.h>
#include <AzFramework/Viewport/ViewportBus.h>
#include <GridMate/Memory.h>
#include <AzFramework/Physics/HeightfieldProviderBus.h>
#include "Application.h"
#include <AzFramework/AzFrameworkModule.h>
@ -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<AZ::SerializeContext*>(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<int>(type));
}
}
struct DeprecatedAliasesKeyVisitor
: AZ::SettingsRegistryInterface::Visitor
{

@ -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

@ -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 <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace Physics
{
void HeightfieldProviderRequests::Reflect(AZ::ReflectContext* context)
{
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<Physics::HeightfieldProviderRequestsBus>("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<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<Physics::HeightMaterialPoint>()->Attribute(AZ::Script::Attributes::Category, "Physics");
}
}
} // namespace Physics

@ -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.

@ -360,6 +360,11 @@ namespace Physics
->Field("MaterialId", &Physics::MaterialId::m_id)
;
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<Physics::MaterialId>()->Attribute(AZ::Script::Attributes::Category, "Physics");
}
}
MaterialId MaterialId::Create()

@ -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

@ -6,6 +6,8 @@
*
*/
#pragma once
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzFramework/XcbConnectionManager.h>
#include <AzFramework/XcbEventHandler.h>

@ -14,7 +14,7 @@
#include <AzCore/Module/DynamicModuleHandle.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/IO/LocalFileIO.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/Asset/AssetUtils.h>
@ -205,7 +205,7 @@ namespace AzToolsFramework::AssetUtils
return platformConfigFilePathsAdded;
}
AZStd::vector<AZ::IO::Path> GetConfigFiles(AZStd::string_view engineRoot, AZStd::string_view assetRoot, AZStd::string_view projectPath,
AZStd::vector<AZ::IO::Path> 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<AZStd::string> 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)

@ -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<AZ::IO::Path> GetConfigFiles(AZStd::string_view engineRoot, AZStd::string_view assetRoot, AZStd::string_view projectPath,
AZStd::vector<AZ::IO::Path> 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.

@ -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
{

@ -9,11 +9,11 @@
#include <AzCore/EBus/Results.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/AssetBrowser/Thumbnails/SourceThumbnail.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <QString>
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);

@ -15,6 +15,7 @@
#include <AzCore/std/sort.h>
#include <AzCore/RTTI/AttributeReader.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzToolsFramework/Commands/EntityStateCommand.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
@ -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);

@ -11,6 +11,8 @@
#include <AzCore/Debug/Profiler.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/std/sort.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
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);
}

@ -10,6 +10,7 @@
#include "EditorEntitySortBus.h"
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Prefab/PrefabPublicNotificationBus.h>
#include <AzCore/Serialization/SerializeContext.h>
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

@ -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);
}

@ -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.

@ -6,10 +6,10 @@
*
*/
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzCore/Utils/Utils.h>
#include <AzToolsFramework/Thumbnails/SourceControlThumbnail.h>
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
#include <AzFramework/API/ApplicationAPI.h>
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();
}

@ -45,6 +45,7 @@ AZ_POP_DISABLE_WARNING
#include <AzToolsFramework/AssetBrowser/EBusFindAssetTypeByName.h>
#include <AzToolsFramework/ComponentMode/ComponentModeDelegate.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
#include <AzToolsFramework/Slice/SliceDataFlagsCommand.h>
#include <AzToolsFramework/Slice/SliceMetadataEntityContextBus.h>
@ -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<AzToolsFramework::Prefab::PrefabFocusPublicInterface>::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);

@ -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;

@ -28,6 +28,7 @@
#include <AzToolsFramework/Manipulators/TranslationManipulators.h>
#include <AzToolsFramework/Maths/TransformUtils.h>
#include <AzToolsFramework/Prefab/PrefabFocusInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
#include <AzToolsFramework/ToolsComponents/EditorLockComponentBus.h>
#include <AzToolsFramework/ToolsComponents/EditorVisibilityBus.h>
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
@ -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<AzToolsFramework::Prefab::PrefabFocusPublicInterface>::Get())
{
AzFramework::EntityContextId editorEntityContextId = GetEntityContextId();
if (AZ::EntityId focusRoot = prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId); focusRoot.IsValid())
{
m_selectedEntityIds.erase(focusRoot);
}
}
}
void EditorTransformComponentSelection::OnTransformChanged(

@ -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 {}

@ -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);

@ -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()

@ -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))

@ -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);

@ -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)

@ -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);

@ -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);

@ -16,6 +16,7 @@
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/UserSettings/UserSettingsComponent.h>
#include <AzCore/Utils/Utils.h>
#include <source/utils/utils.h>
#include <source/utils/applicationManager.h>
@ -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);

@ -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;

@ -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);

@ -749,7 +749,7 @@ namespace AssetProcessor
}
AZStd::vector<AZ::IO::Path> 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

@ -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)

@ -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;

@ -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())
{
m_downloadSectionWidget->hide();
}
else
{
if (m_downloadController->IsDownloadQueueEmpty())
// Setup gem download rows for gems that are already in the queue
const AZStd::vector<QString>& downloadQueue = m_downloadController->GetDownloadQueue();
for (const QString& gemName : downloadQueue)
{
widget->hide();
GemDownloadAdded(gemName);
}
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<QString>& 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);
// connect to download controller data changed
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);
}
QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
nameProgressLayout->addSpacerItem(spacer);
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("<a href=\"%1\">Cancel</a>").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<QString>& downloadQueue = m_downloadController->GetDownloadQueue();
QLabel* numDownloads = m_downloadingListWidget->findChild<QLabel*>("NumDownloadsInProgressLabel");
numDownloads->setText(QString("%1 %2")
.arg(downloadQueue.size())
.arg(downloadQueue.size() == 1 ? tr("download in progress...") : tr("downloads in progress...")));
m_downloadingListWidget->show();
}
QLabel* cancelText = new QLabel(QString("<a href=\"%1\">Cancel</a>").arg(gemName));
cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated);
nameProgressLayout->addWidget(cancelText);
downloadingItemLayout->addLayout(nameProgressLayout);
void CartOverlayWidget::GemDownloadRemoved(const QString& gemName)
{
QWidget* gemToRemove = m_downloadingListWidget->findChild<QWidget*>(gemName);
if (gemToRemove)
{
gemToRemove->deleteLater();
}
QProgressBar* downloadProgessBar = new QProgressBar();
downloadingItemLayout->addWidget(downloadProgessBar);
downloadProgessBar->setValue(downloadingGemNumber == 0 ? downloadProgress : 0);
}
if (m_downloadController->IsDownloadQueueEmpty())
{
m_downloadSectionWidget->hide();
}
else
{
size_t downloadQueueSize = m_downloadController->GetDownloadQueue().size();
QLabel* numDownloads = m_downloadingListWidget->findChild<QLabel*>("NumDownloadsInProgressLabel");
numDownloads->setText(QString("%1 %2")
.arg(downloadQueueSize)
.arg(downloadQueueSize == 1 ? tr("download in progress...") : tr("downloads in progress...")));
}
}
widget->setUpdatesEnabled(true);
widget->show();
void CartOverlayWidget::GemDownloadProgress(const QString& gemName, int percentage)
{
QWidget* gemToUpdate = m_downloadingListWidget->findChild<QWidget*>(gemName);
if (gemToUpdate)
{
QLabel* progressLabel = gemToUpdate->findChild<QLabel*>("DownloadProgressLabel");
if (progressLabel)
{
progressLabel->setText(QString("%1%").arg(percentage));
}
};
QProgressBar* progressBar = gemToUpdate->findChild<QProgressBar*>("DownloadProgressBar");
if (progressBar)
{
progressBar->setValue(percentage);
}
}
}
auto downloadEnded = [=](const QString& /*gemName*/, bool /*success*/)
{
update(0); // update the list to remove the gem that has finished
};
// connect to download controller data changed
connect(m_downloadController, &DownloadController::GemDownloadProgress, this, update);
connect(m_downloadController, &DownloadController::Done, this, downloadEnded);
update(0);
void CartOverlayWidget::GemDownloadComplete(const QString& gemName, bool /*success*/)
{
GemDownloadRemoved(gemName); // update the list to remove the gem that has finished
}
QVector<Tag> CartOverlayWidget::GetTagsFromModelIndices(const QVector<QModelIndex>& gems) const

@ -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<Tag> GetTagsFromModelIndices(const QVector<QModelIndex>& 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;
};

@ -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);
}
}

@ -221,7 +221,6 @@ namespace O3DE::ProjectManager
ResetGemStatusFilter();
ResetGemOriginFilter();
ResetTypeFilter();
ResetPlatformFilter();
ResetFeatureFilter();
}

@ -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)
{

@ -39,7 +39,6 @@ namespace PythonBindingsExample
AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusConnect();
// prepare the Python binding gem(s)
CalculateExecutablePath();
Start(Descriptor());
AZ::SerializeContext* context;

@ -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&));

@ -202,8 +202,6 @@ namespace AZ
bool skipSystem = commandLine->HasSwitch("skipsystem");
bool isDryRun = commandLine->HasSwitch("dryrun");
const char* appRoot = const_cast<const Application&>(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<AZ::ComponentApplication::Descriptor>())
@ -238,7 +236,7 @@ namespace AZ
if (!skipSystem)
{
result = ConvertSystemSettings(documents, *reinterpret_cast<AZ::ComponentApplication::Descriptor*>(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";

@ -43,7 +43,7 @@ namespace AZ
using PathDocumentContainer = AZStd::vector<PathDocumentPair>;
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);

@ -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 {}

@ -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

@ -439,13 +439,6 @@ namespace AssetValidation
bool GetDefaultSeedListFiles(AZStd::vector<AZStd::string>& 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<AzFramework::AssetSeedList, AZStd::string> 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);
}

@ -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;

@ -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 {}

@ -37,6 +37,7 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject
float m_padding;
bool m_useReflectionProbe;
bool m_useParallaxCorrection;
float m_exposure;
};
ReflectionProbeData m_reflectionProbeData;

@ -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);
}
}
}

@ -46,6 +46,7 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject
float m_padding;
bool m_useReflectionProbe;
bool m_useParallaxCorrection;
float m_exposure;
};
ReflectionProbeData m_reflectionProbeData;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save