From 7d594a6823a79ea458bd5bddf51fbc780fc5ef5d Mon Sep 17 00:00:00 2001 From: Peng Date: Fri, 21 May 2021 09:12:29 -0700 Subject: [PATCH 01/41] ATOM-15576 [RHI][Vulkan][Android] Set the correct image type for 3D image null descriptor JIRA: https://jira.agscollab.com/browse/ATOM-15576 --- Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.cpp index cdacd2578f..791fa006b0 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.cpp @@ -180,6 +180,7 @@ namespace AZ for (uint32_t imageIndex = static_cast(NullDescriptorManager::ImageTypes::General2D); imageIndex < static_cast(NullDescriptorManager::ImageTypes::Count); imageIndex++) { // different options for the images + imageCreateInfo.imageType = (imageIndex >= static_cast(NullDescriptorManager::ImageTypes::General3D)) ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D; imageCreateInfo.extent = { m_imageNullDescriptor.m_images[imageIndex].m_dimension, m_imageNullDescriptor.m_images[imageIndex].m_dimension, 1 }; imageCreateInfo.samples = m_imageNullDescriptor.m_images[imageIndex].m_sampleCountFlag; imageCreateInfo.format = m_imageNullDescriptor.m_images[imageIndex].m_format; From 952901f55b7ebade4c38abc524344330ffb0efa6 Mon Sep 17 00:00:00 2001 From: scottr Date: Tue, 25 May 2021 11:33:59 -0700 Subject: [PATCH 02/41] [cpack_installer] adding setup script to install cmake, python, and registering the engine --- .../CMake/cmake-3.19.1-win64-x64.zip | 3 + scripts/setup.bat | 93 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 Tools/Redistributables/CMake/cmake-3.19.1-win64-x64.zip create mode 100644 scripts/setup.bat diff --git a/Tools/Redistributables/CMake/cmake-3.19.1-win64-x64.zip b/Tools/Redistributables/CMake/cmake-3.19.1-win64-x64.zip new file mode 100644 index 0000000000..fc3a243f06 --- /dev/null +++ b/Tools/Redistributables/CMake/cmake-3.19.1-win64-x64.zip @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e95d70549f306adb46e0f131dcecdbcbc6412d3a1e073c2c0078812391bf21d3 +size 36098689 diff --git a/scripts/setup.bat b/scripts/setup.bat new file mode 100644 index 0000000000..34251ad861 --- /dev/null +++ b/scripts/setup.bat @@ -0,0 +1,93 @@ +@echo off +rem +rem All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +rem its licensors. +rem +rem For complete copyright and license terms please see the LICENSE at the root of this +rem distribution (the "License"). All use of this software is governed by the License, +rem or, if provided, by the license below or the license accompanying this file. Do not +rem remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +rem + +pushd %~dp0% + +pushd %~dp0.. +set ENGINE_ROOT=%CD% +popd + +set cmake_version=3.19.1 + +if not "%1"=="" ( + set LY_3RDPARTY_PATH=%1 +) +if "%LY_3RDPARTY_PATH%"=="" goto no_3rd_party + +if not exist %LY_3RDPARTY_PATH% mkdir %LY_3RDPARTY_PATH% +goto install_cmake + +:no_3rd_party +echo A path to where the 3rd party folder is required for setup. +echo Either supply one through the LY_3RDPARTY_PATH environment +echo variable or as an argument to this script +goto fail + + +:install_cmake +set cmake_install_path=%LY_3RDPARTY_PATH%\CMake\%cmake_version%\Windows +set cmake_archive_name=cmake-%cmake_version%-win64-x64 +set cmake_archive_path="%ENGINE_ROOT%\Tools\Redistributables\CMake\%cmake_archive_name%.zip" +if exist "%cmake_install_path%\bin\cmake.exe" goto install_python + +echo Installing CMake %cmake_version% to %cmake_install_path% +if not exist %cmake_install_path% mkdir %cmake_install_path% +powershell.exe -nologo -noprofile -command^ + "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('%cmake_archive_path%', '%cmake_install_path%'); }" +if ERRORLEVEL 1 goto cmake_failed + +set cmake_extracted_path=%cmake_install_path%\%cmake_archive_name% +for /d %%a in ("%cmake_extracted_path%\*") do move "%%a" "%cmake_install_path%\" +rmdir %cmake_extracted_path% + +goto success + +if ERRORLEVEL 1 goto cmake_failed +set LY_CMAKE_PATH="%cmake_install_path%\bin" +goto install_python + +:cmake_failed +echo Failed to extract cmake to path %cmake_install_path% +goto fail + + +:install_python +echo Installing python... +call %ENGINE_ROOT%\python\get_python.bat +if ERRORLEVEL 1 goto python_failed +goto register_engine + +:python_failed +echo Failed to acquire python +goto fail + + +:register_engine +echo Registering engine... +call %ENGINE_ROOT%\scripts\o3de.bat register --this-engine +if ERRORLEVEL 1 goto registration_failed +goto success + +:registration_failed +echo Failed to register the engine +goto fail + + +:fail +echo O3DE setup failed +popd +exit /b 1 + +:success +echo O3DE setup complete +popd +exit /b %ERRORLEVEL% From 87ff564badb54fed90c8c906379aedad03112974 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Tue, 25 May 2021 13:15:10 -0700 Subject: [PATCH 03/41] ATOM-14838 Make Parallax Look Decent By Default Updated material types to have default parallax settings of POM, Low quality, 0.05 scale. That way the parallax effect will show up as soon as a user adds a heightmap. Updated StandardMultilayerPBR_Displacement.lua to control the o_parallax_feature_enabled, so we can have the material's parallax.enable=true by default. Again this is to allow parallax behavior to show up as soon as the user adds a heightmap or adjusts the displacement offset. Note that even though we have a functor to drive the feature based on displacement settings, we still need the parallax.enable flag that that the user can set to false when they want to use displacement blending but not parallax. Updated test materials to maintain their prior implied settings. --- .../Materials/Types/EnhancedPBR.materialtype | 4 +- .../Types/StandardMultilayerPBR.materialtype | 17 +++-- .../StandardMultilayerPBR_Displacement.lua | 66 ++++++++++++++++--- .../Materials/Types/StandardPBR.materialtype | 4 +- .../001_ManyFeatures.material | 2 +- .../002_ParallaxPdo.material | 4 +- .../004_UseVertexColors.material | 5 +- 7 files changed, 76 insertions(+), 26 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index 954e01c592..48b576c768 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -973,7 +973,7 @@ "displayName": "Heightmap Scale", "description": "The total height of the heightmap in local model units.", "type": "Float", - "defaultValue": 0.0, + "defaultValue": 0.05, "min": 0.0, "softMax": 0.1, "connection": { @@ -1011,7 +1011,7 @@ "description": "Select the algorithm to use for parallax mapping.", "type": "Enum", "enumValues": [ "Basic", "Steep", "POM", "Relief", "ContactRefinement" ], - "defaultValue": "Basic", + "defaultValue": "POM", "connection": { "type": "ShaderOption", "id": "o_parallax_algorithm" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype index 274cb4dcb5..05ba40ddae 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype @@ -369,15 +369,14 @@ ], "parallax": [ { + // Note parallax is enabled by default so that as soon as a user hooks up displacement settings they will see some parallax applied. + // The functor that controls parallax will set o_parallax_feature_enabled=false when all the individual layers have no displacement, so + // a default value of true here will not have any initial impact on performance. "id": "enable", "displayName": "Enable", "description": "Whether to enable the parallax feature for this material.", "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderOption", - "id": "o_parallax_feature_enabled" - } + "defaultValue": true }, { "id": "parallaxUv", @@ -409,7 +408,7 @@ "description": "Quality of parallax mapping.", "type": "Enum", "enumValues": [ "Low", "Medium", "High", "Ultra" ], - "defaultValue": "Medium", + "defaultValue": "Low", "connection": { "type": "ShaderOption", "id": "o_parallax_quality" @@ -1141,7 +1140,7 @@ "displayName": "Scale", "description": "The total height of the displacement texture map in local model units.", "type": "Float", - "defaultValue": 0.0, + "defaultValue": 0.05, "min": 0.0, "softMax": 0.1, "connection": { @@ -1847,7 +1846,7 @@ "displayName": "Scale", "description": "The total height of the displacement texture map in local model units.", "type": "Float", - "defaultValue": 0.0, + "defaultValue": 0.05, "min": 0.0, "softMax": 0.1, "connection": { @@ -2553,7 +2552,7 @@ "displayName": "Scale", "description": "The total height of the displacement texture map in local model units.", "type": "Float", - "defaultValue": 0.0, + "defaultValue": 0.05, "min": 0.0, "softMax": 0.1, "connection": { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua index 34a067577d..d2bf8f28d3 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua @@ -35,6 +35,10 @@ function GetMaterialPropertyDependencies() } end +function GetShaderOptionDependencies() + return {"o_parallax_feature_enabled"} +end + -- These values must align with LayerBlendSource in StandardMultilayerPBR_Common.azsli. LayerBlendSource_BlendMaskTexture = 0 LayerBlendSource_BlendMaskVertexColors = 1 @@ -50,6 +54,39 @@ function BlendSourceUsesDisplacement(context) return blendSourceIncludesDisplacement end +function IsParallaxNeededForLayer(context, layerNumber) + local enableLayer = true + if(layerNumber > 1) then -- layer 1 is always enabled, it is the implicit base layer + enableLayer = context:GetMaterialPropertyValue_bool("blend.enableLayer" .. layerNumber) + end + + if not enableLayer then + return false + end + + local parallaxGroupName = "layer" .. layerNumber .. "_parallax." + + local factor = context:GetMaterialPropertyValue_float(parallaxGroupName .. "factor") + local offset = context:GetMaterialPropertyValue_float(parallaxGroupName .. "offset") + + if factor == 0.0 and offset == 0.0 then + return false + end + + local hasTexture = nil ~= context:GetMaterialPropertyValue_Image(parallaxGroupName .. "textureMap") + local useTexture = context:GetMaterialPropertyValue_bool(parallaxGroupName .. "useTexture") + + if not hasTexture or not useTexture then + factorLayer = 0.0 + end + + if factor == 0.0 and offset == 0.0 then + return false + end + + return true +end + -- Calculates the min and max displacement height values encompassing all enabled layers. -- @return a table with two values {min,max}. Negative values are below the surface and positive values are above the surface. function CalcOverallHeightRange(context) @@ -114,21 +151,32 @@ function Process(context) local heightMinMax = CalcOverallHeightRange(context) context:SetShaderConstant_float("m_displacementMin", heightMinMax[0]) context:SetShaderConstant_float("m_displacementMax", heightMinMax[1]) + + local parallaxFeatureEnabled = context:GetMaterialPropertyValue_bool("parallax.enable") + if parallaxFeatureEnabled then + if not IsParallaxNeededForLayer(context, 1) and + not IsParallaxNeededForLayer(context, 2) and + not IsParallaxNeededForLayer(context, 3) then + parallaxFeatureEnabled = false + end + end + + context:SetShaderOptionValue_bool("o_parallax_feature_enabled", parallaxFeatureEnabled) end function ProcessEditor(context) - local enable = context:GetMaterialPropertyValue_bool("parallax.enable") + local enableParallaxSettings = context:GetMaterialPropertyValue_bool("parallax.enable") - local visibility = MaterialPropertyVisibility_Enabled - if(not enable) then - visibility = MaterialPropertyVisibility_Hidden + local parallaxSettingVisibility = MaterialPropertyVisibility_Enabled + if(not enableParallaxSettings) then + parallaxSettingVisibility = MaterialPropertyVisibility_Hidden end - context:SetMaterialPropertyVisibility("parallax.parallaxUv", visibility) - context:SetMaterialPropertyVisibility("parallax.algorithm", visibility) - context:SetMaterialPropertyVisibility("parallax.quality", visibility) - context:SetMaterialPropertyVisibility("parallax.pdo", visibility) - context:SetMaterialPropertyVisibility("parallax.showClipping", visibility) + context:SetMaterialPropertyVisibility("parallax.parallaxUv", parallaxSettingVisibility) + context:SetMaterialPropertyVisibility("parallax.algorithm", parallaxSettingVisibility) + context:SetMaterialPropertyVisibility("parallax.quality", parallaxSettingVisibility) + context:SetMaterialPropertyVisibility("parallax.pdo", parallaxSettingVisibility) + context:SetMaterialPropertyVisibility("parallax.showClipping", parallaxSettingVisibility) if BlendSourceUsesDisplacement(context) then context:SetMaterialPropertyVisibility("blend.displacementBlendDistance", MaterialPropertyVisibility_Enabled) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype index 2b0d09bc5c..2d848b2774 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype @@ -913,7 +913,7 @@ "displayName": "Heightmap Scale", "description": "The total height of the heightmap in local model units.", "type": "Float", - "defaultValue": 0.0, + "defaultValue": 0.05, "min": 0.0, "softMax": 0.1, "connection": { @@ -951,7 +951,7 @@ "description": "Select the algorithm to use for parallax mapping.", "type": "Enum", "enumValues": [ "Basic", "Steep", "POM", "Relief", "ContactRefinement" ], - "defaultValue": "Basic", + "defaultValue": "POM", "connection": { "type": "ShaderOption", "id": "o_parallax_algorithm" diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material index 17353a0603..1c02f56af6 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material @@ -132,7 +132,7 @@ "rotateDegrees": -57.599998474121097 }, "parallax": { - "enable": true + "quality": "Medium" }, "uv": { "center": [ diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material index 8cddab24bc..64adf317a9 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material @@ -48,8 +48,8 @@ "textureMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg" }, "parallax": { - "enable": true, - "pdo": true + "pdo": true, + "quality": "Medium" } } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material index 3201fa3864..ea3ea8b519 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material @@ -6,6 +6,9 @@ "properties": { "blend": { "blendSource": "BlendMaskVertexColors" + }, + "parallax": { + "quality": "Medium" } } -} +} \ No newline at end of file From 1f297fc8ac04d8dfdcca1000d113bda10b0fd5bd Mon Sep 17 00:00:00 2001 From: moudgils Date: Tue, 25 May 2021 14:41:14 -0700 Subject: [PATCH 04/41] Updating LuminanceHistogramGenerator to use RWStructuredBuffer as RWBuffer doeesnt work on Metal when combined with atomic operations --- .../Shaders/PostProcessing/LuminanceHistogramGenerator.azsl | 2 +- .../Shaders/PostProcessing/LuminanceHistogramGenerator.shader | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl index 05cc870eea..9d01a12fd6 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl @@ -20,7 +20,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass { Texture2D m_inputTexture; - RWBuffer m_outputTexture; + RWStructuredBuffer m_outputTexture; } groupshared uint shared_histogramBins[NUM_HISTOGRAM_BINS]; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader index 566144bab8..f3dd11e11a 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader @@ -12,7 +12,5 @@ "type": "Compute" } ] - }, - "DisabledRHIBackends": ["metal"] - + } } From 76c23cda6a02129e575c2beb39359d1894fa8d74 Mon Sep 17 00:00:00 2001 From: balibhan Date: Wed, 26 May 2021 10:17:44 +0530 Subject: [PATCH 05/41] Add all datatype parameters script --- ...vents_AllParamDatatypes_CreationSuccess.py | 210 ++++++++++++++++++ .../scripting/TestSuite_Periodic.py | 30 ++- 2 files changed, 236 insertions(+), 4 deletions(-) create mode 100644 AutomatedTesting/Gem/PythonTests/scripting/ScriptEvents_AllParamDatatypes_CreationSuccess.py diff --git a/AutomatedTesting/Gem/PythonTests/scripting/ScriptEvents_AllParamDatatypes_CreationSuccess.py b/AutomatedTesting/Gem/PythonTests/scripting/ScriptEvents_AllParamDatatypes_CreationSuccess.py new file mode 100644 index 0000000000..4beedec7cf --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/scripting/ScriptEvents_AllParamDatatypes_CreationSuccess.py @@ -0,0 +1,210 @@ +""" +All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +its licensors. + +For complete copyright and license terms please see the LICENSE at the root of this +distribution (the "License"). All use of this software is governed by the License, +or, if provided, by the license below or the license accompanying this file. Do not +remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +""" + + +# fmt: off +class Tests(): + new_event_created = ("New Script Event created", "New Script Event not created") + child_event_created = ("Child Event created", "Child Event not created") + params_added = ("New parameters added", "New parameters are not added") + file_saved = ("Script event file saved", "Script event file did not save") + node_found = ("Node found in Script Canvas", "Node not found in Script Canvas") +# fmt: on + + +def ScriptEvents_AllParamDatatypes_CreationSuccess(): + """ + Summary: + Parameters of all types can be created. + + Expected Behavior: + The Method handles the large number of Parameters gracefully. + Parameters of all data types can be successfully created. + Updated ScriptEvent toast appears in Script Canvas. + + Test Steps: + 1) Open Asset Editor + 2) Initially create new Script Event file with one method + 3) Add new method and set name to it + 4) Add new parameters of each type + 5) Verify if parameters are added + 6) Expand the parameter rows + 7) Set different names and datatypes for each parameter + 8) Save file and verify node in SC Node Palette + 9) Close Asset Editor + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ + import os + from utils import TestHelper as helper + import pyside_utils + + # Open 3D Engine imports + import azlmbr.legacy.general as general + import azlmbr.editor as editor + import azlmbr.bus as bus + + # Pyside imports + from PySide2 import QtWidgets, QtTest, QtCore + + GENERAL_WAIT = 1.0 # seconds + + FILE_PATH = os.path.join("AutomatedTesting", "TestAssets", "test_file.scriptevents") + N_VAR_TYPES = 10 # Top 10 variable types + TEST_METHOD_NAME = "test_method_name" + + editor_window = pyside_utils.get_editor_main_window() + asset_editor = asset_editor_widget = container = menu_bar = None + sc = node_palette = tree = search_frame = search_box = None + + def initialize_asset_editor_qt_objects(): + nonlocal asset_editor, asset_editor_widget, container, menu_bar + asset_editor = editor_window.findChild(QtWidgets.QDockWidget, "Asset Editor") + asset_editor_widget = asset_editor.findChild(QtWidgets.QWidget, "AssetEditorWindowClass") + container = asset_editor_widget.findChild(QtWidgets.QWidget, "ContainerForRows") + menu_bar = asset_editor_widget.findChild(QtWidgets.QMenuBar) + + def initialize_sc_qt_objects(): + nonlocal sc, node_palette, tree, search_frame, search_box + sc = editor_window.findChild(QtWidgets.QDockWidget, "Script Canvas") + if sc.findChild(QtWidgets.QDockWidget, "NodePalette") is None: + action = pyside_utils.find_child_by_pattern(sc, {"text": "Node Palette", "type": QtWidgets.QAction}) + action.trigger() + node_palette = sc.findChild(QtWidgets.QDockWidget, "NodePalette") + tree = node_palette.findChild(QtWidgets.QTreeView, "treeView") + search_frame = node_palette.findChild(QtWidgets.QFrame, "searchFrame") + search_box = search_frame.findChild(QtWidgets.QLineEdit, "searchFilter") + + def save_file(): + editor.AssetEditorWidgetRequestsBus(bus.Broadcast, "SaveAssetAs", FILE_PATH) + action = pyside_utils.find_child_by_pattern(menu_bar, {"type": QtWidgets.QAction, "iconText": "Save"}) + action.trigger() + # wait till file is saved, to validate that check the text of QLabel at the bottom of the AssetEditor, + # if there are no unsaved changes we will not have any * in the text + label = asset_editor.findChild(QtWidgets.QLabel, "textEdit") + return helper.wait_for_condition(lambda: "*" not in label.text(), 3.0) + + def expand_container_rows(object_name): + children = container.findChildren(QtWidgets.QFrame, object_name) + for child in children: + check_box = child.findChild(QtWidgets.QCheckBox) + if check_box and not check_box.isChecked(): + QtTest.QTest.mouseClick(check_box, QtCore.Qt.LeftButton, QtCore.Qt.NoModifier) + + def node_palette_search(node_name): + search_box.setText(node_name) + helper.wait_for_condition(lambda: search_box.text() == node_name, 1.0) + # Try clicking ENTER in search box multiple times + for _ in range(20): + QtTest.QTest.keyClick(search_box, QtCore.Qt.Key_Enter, QtCore.Qt.NoModifier) + if pyside_utils.find_child_by_pattern(tree, {"text": node_name}) is not None: + break + + def verify_added_params(): + for index in range(N_VAR_TYPES): + if container.findChild(QtWidgets.QFrame, f"[{index}]") is None: + return False + return True + + # 1) Open Asset Editor + general.idle_enable(True) + # Initially close the Asset Editor and then reopen to ensure we don't have any existing assets open + general.close_pane("Asset Editor") + general.open_pane("Asset Editor") + helper.wait_for_condition(lambda: general.is_pane_visible("Asset Editor"), 5.0) + + # 2) Initially create new Script Event file with one method + initialize_asset_editor_qt_objects() + action = pyside_utils.find_child_by_pattern(menu_bar, {"type": QtWidgets.QAction, "text": "Script Events"}) + action.trigger() + result = helper.wait_for_condition( + lambda: container.findChild(QtWidgets.QFrame, "Events") is not None + and container.findChild(QtWidgets.QFrame, "Events").findChild(QtWidgets.QToolButton, "") is not None, + 3 * GENERAL_WAIT, + ) + Report.result(Tests.new_event_created, result) + + # 3) Add new method and set name to it + add_event = container.findChild(QtWidgets.QFrame, "Events").findChild(QtWidgets.QToolButton, "") + add_event.click() + result = helper.wait_for_condition( + lambda: asset_editor_widget.findChild(QtWidgets.QFrame, "EventName") is not None, GENERAL_WAIT + ) + Report.result(Tests.child_event_created, result) + expand_container_rows("EventName") + expand_container_rows("Name") + initialize_asset_editor_qt_objects() + children = container.findChildren(QtWidgets.QFrame, "Name") + for child in children: + line_edit = child.findChild(QtWidgets.QLineEdit) + if line_edit is not None and line_edit.text() == "MethodName": + line_edit.setText(TEST_METHOD_NAME) + + # 4) Add new parameters of each type + helper.wait_for_condition(lambda: container.findChild(QtWidgets.QFrame, "Parameters") is not None, 2.0) + parameters = container.findChild(QtWidgets.QFrame, "Parameters") + add_param = parameters.findChild(QtWidgets.QToolButton, "") + for _ in range(N_VAR_TYPES): + add_param.click() + + # 5) Verify if parameters are added + result = helper.wait_for_condition(verify_added_params, 3.0) + Report.result(Tests.params_added, result) + + # 6) Expand the parameter rows (to render QFrame 'Type' for each param) + for index in range(N_VAR_TYPES): + expand_container_rows(f"[{index}]") + + # 7) Set different names and datatypes for each parameter + expand_container_rows("Name") + children = container.findChildren(QtWidgets.QFrame, "Name") + index = 0 + for child in children: + line_edit = child.findChild(QtWidgets.QLineEdit) + if line_edit is not None and line_edit.text() == "ParameterName": + line_edit.setText(f"param_{index}") + index += 1 + + children = container.findChildren(QtWidgets.QFrame, "Type") + index = 0 + for child in children: + combo_box = child.findChild(QtWidgets.QComboBox) + if combo_box is not None and index < N_VAR_TYPES: + combo_box.setCurrentIndex(index) + index += 1 + + # 8) Save file and verify node in SC Node Palette + Report.result(Tests.file_saved, save_file()) + general.open_pane("Script Canvas") + helper.wait_for_condition(lambda: general.is_pane_visible("Script Canvas"), 5.0) + initialize_sc_qt_objects() + node_palette_search(TEST_METHOD_NAME) + get_node_index = lambda: pyside_utils.find_child_by_pattern(tree, {"text": TEST_METHOD_NAME}) is not None + result = helper.wait_for_condition(get_node_index, 2.0) + Report.result(Tests.node_found, result) + + # 9) Close Asset Editor + general.close_pane("Asset Editor") + general.close_pane("Script Canvas") + + +if __name__ == "__main__": + import ImportPathHelper as imports + + imports.init() + from utils import Report + + Report.start_test(ScriptEvents_AllParamDatatypes_CreationSuccess) diff --git a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py index 85d0b4523f..91d6b3e53e 100755 --- a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py +++ b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py @@ -113,10 +113,6 @@ class TestAutomation(TestAutomationBase): from . import Debugger_HappyPath_TargetMultipleGraphs as test_module self._run_test(request, workspace, editor, test_module) - def test_Debugging_TargetMultipleGraphs(self, request, workspace, editor, launcher_platform, project): - from . import Debugging_TargetMultipleGraphs as test_module - self._run_test(request, workspace, editor, test_module) - @pytest.mark.parametrize("level", ["tmp_level"]) def test_Debugger_HappyPath_TargetMultipleEntities(self, request, workspace, editor, launcher_platform, project, level): def teardown(): @@ -317,4 +313,30 @@ class TestScriptCanvasTests(object): auto_test_mode=False, timeout=60, ) + + def test_ScriptEvents_AllParamDatatypes_CreationSuccess(self, request, workspace, editor, launcher_platform): + def teardown(): + file_system.delete( + [os.path.join(workspace.paths.project(), "TestAssets", "test_file.scriptevents")], True, True + ) + request.addfinalizer(teardown) + file_system.delete( + [os.path.join(workspace.paths.project(), "TestAssets", "test_file.scriptevents")], True, True + ) + expected_lines = [ + "Success: New Script Event created", + "Success: Child Event created", + "Success: New parameters added", + "Success: Script event file saved", + "Success: Node found in Script Canvas", + ] + hydra.launch_and_validate_results( + request, + TEST_DIRECTORY, + editor, + "ScriptEvents_AllParamDatatypes_CreationSuccess.py", + expected_lines, + auto_test_mode=False, + timeout=60, + ) \ No newline at end of file From a66345e7cbbd3be39fa32391dd25a228cac63593 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Wed, 26 May 2021 11:42:25 -0700 Subject: [PATCH 06/41] ATOM-13828 UV Transform Center Default Middle Updated all UV transform property sets for Atom's core material types to have 0.5 as the transform center. --- .../Assets/Materials/Types/EnhancedPBR.materialtype | 4 ++-- .../Common/Assets/Materials/Types/Skin.materialtype | 2 +- .../Materials/Types/StandardMultilayerPBR.materialtype | 8 ++++---- .../Assets/Materials/Types/StandardPBR.materialtype | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index 48b576c768..a085afa327 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -725,7 +725,7 @@ "description": "Center point for scaling and rotation transformations.", "type": "vector2", "vectorLabels": [ "U", "V" ], - "defaultValue": [ 0.0, 0.0 ] + "defaultValue": [ 0.5, 0.5 ] }, { "id": "tileU", @@ -1388,7 +1388,7 @@ "description": "Center point for scaling and rotation transformations.", "type": "vector2", "vectorLabels": [ "U", "V" ], - "defaultValue": [ 0.0, 0.0 ] + "defaultValue": [ 0.5, 0.5 ] }, { "id": "tileU", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index 101a03b907..044b267645 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -909,7 +909,7 @@ "description": "Center point for scaling and rotation transformations.", "type": "vector2", "vectorLabels": [ "U", "V" ], - "defaultValue": [ 0.0, 0.0 ] + "defaultValue": [ 0.5, 0.5 ] }, { "id": "tileU", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype index 05ba40ddae..ec1298ae77 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype @@ -444,7 +444,7 @@ "description": "Center point for scaling and rotation transformations.", "type": "vector2", "vectorLabels": [ "U", "V" ], - "defaultValue": [ 0.0, 0.0 ] + "defaultValue": [ 0.5, 0.5 ] }, { "id": "tileU", @@ -1169,7 +1169,7 @@ "description": "Center point for scaling and rotation transformations.", "type": "vector2", "vectorLabels": [ "U", "V" ], - "defaultValue": [ 0.0, 0.0 ] + "defaultValue": [ 0.5, 0.5 ] }, { "id": "tileU", @@ -1875,7 +1875,7 @@ "description": "Center point for scaling and rotation transformations.", "type": "vector2", "vectorLabels": [ "U", "V" ], - "defaultValue": [ 0.0, 0.0 ] + "defaultValue": [ 0.5, 0.5 ] }, { "id": "tileU", @@ -2581,7 +2581,7 @@ "description": "Center point for scaling and rotation transformations.", "type": "vector2", "vectorLabels": [ "U", "V" ], - "defaultValue": [ 0.0, 0.0 ] + "defaultValue": [ 0.5, 0.5 ] }, { "id": "tileU", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype index 2d848b2774..04e6c0f501 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype @@ -669,7 +669,7 @@ "description": "Center point for scaling and rotation transformations.", "type": "vector2", "vectorLabels": [ "U", "V" ], - "defaultValue": [ 0.0, 0.0 ] + "defaultValue": [ 0.5, 0.5 ] }, { "id": "tileU", From b72cb2c60157896530b61d971e2d437eff9824df Mon Sep 17 00:00:00 2001 From: jckand-amzn Date: Wed, 26 May 2021 14:41:08 -0500 Subject: [PATCH 07/41] SPEC-6685: Updating/adding test summaries for TestRail decoupling effort --- ...rfaceMaskFilter_BasicSurfaceTagCreation.py | 19 ++++++++ ...getationInstances_DespawnWhenOutOfRange.py | 19 ++++++++ .../GradientGenerators_Incompatibilities.py | 17 ++++++- .../GradientModifiers_Incompatibilities.py | 17 ++++++- ...ClearingPinnedEntitySetsPreviewToOrigin.py | 13 ----- .../AreaNodes_DependentComponentsAdded.py | 20 ++++++++ .../AreaNodes_EntityCreatedOnNodeAdd.py | 18 +++++++ .../AreaNodes_EntityRemovedOnNodeDelete.py | 19 ++++++++ .../ComponentUpdates_UpdateGraph.py | 48 ++++++++++++------- .../EditorScripts/CreateNewGraph.py | 19 ++++++++ .../Edit_DisabledNodeDuplication.py | 18 +++++++ .../Edit_UndoNodeDelete_SliceEntity.py | 30 +++++++----- .../GradientMixer_NodeConstruction.py | 21 ++++++++ ...entModifierNodes_EntityCreatedOnNodeAdd.py | 19 ++++++++ ...ModifierNodes_EntityRemovedOnNodeDelete.py | 19 ++++++++ .../GradientNodes_DependentComponentsAdded.py | 21 ++++++++ .../GradientNodes_EntityCreatedOnNodeAdd.py | 19 ++++++++ ...GradientNodes_EntityRemovedOnNodeDelete.py | 20 ++++++++ .../GraphClosed_OnEntityDelete.py | 20 ++++++++ .../GraphClosed_OnLevelChange.py | 19 ++++++++ .../EditorScripts/GraphClosed_TabbedGraph.py | 20 ++++++++ .../GraphUpdates_UpdateComponents.py | 40 ++++++++++------ .../LandscapeCanvasComponent_AddedRemoved.py | 20 ++++++++ .../LandscapeCanvas_SliceCreateInstantiate.py | 15 ++++-- .../LayerBlender_NodeConstruction.py | 21 ++++++++ .../LayerExtenderNodes_ComponentEntitySync.py | 19 ++++++++ .../ShapeNodes_EntityCreatedOnNodeAdd.py | 19 ++++++++ .../ShapeNodes_EntityRemovedOnNodeDelete.py | 22 ++++++++- ...otConnections_UpdateComponentReferences.py | 21 ++++++++ 29 files changed, 547 insertions(+), 65 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_BasicSurfaceTagCreation.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_BasicSurfaceTagCreation.py index 4f58a23a19..730a557a9e 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_BasicSurfaceTagCreation.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_BasicSurfaceTagCreation.py @@ -23,6 +23,25 @@ class TestSurfaceMaskFilter_BasicSurfaceTagCreation(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="TestSurfaceMaskFilter_BasicSurfaceTagCreation", args=["level"]) def run_test(self): + """ + Summary: + Verifies basic surface tag value equality + + Expected Behavior: + Surface tags of the same name are equal, and different names aren't. + + Test Steps: + 1) Open level + 2) Create 2 new surface tags of identical names and verify they resolve as equal. + 3) Create another new tag of a different name and verify they resolve as different. + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ self.log("SurfaceTag test started") # Create a level diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/VegetationInstances_DespawnWhenOutOfRange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/VegetationInstances_DespawnWhenOutOfRange.py index c25761d655..46c5483988 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/VegetationInstances_DespawnWhenOutOfRange.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/VegetationInstances_DespawnWhenOutOfRange.py @@ -33,6 +33,25 @@ class TestVegetationInstances_DespawnWhenOutOfRange(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix='VegetationInstances_DespawnWhenOutOfRange', args=['level']) def run_test(self): + """ + Summary: + Verifies that vegetation instances properly spawn/despawn based on camera range. + + Expected Behavior: + Vegetation instances despawn when out of camera range. + + Test Steps: + 1) Create a new level + 2) Create a simple vegetation area, and set the view position near the spawner. Verify instances plant. + 3) Move the view position away from the spawner. Verify instances despawn. + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ # Create a new level self.test_success = self.create_level( diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py index cc9a15bba0..c37bc9780f 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py @@ -28,8 +28,21 @@ class TestGradientGeneratorIncompatibilities(EditorTestHelper): def run_test(self): """ Summary: - Verify that Entities are not active when a Gradient Generator and incompatible component are both present - on the same Entity. + This test verifies that components are disabled when conflicting components are present on the same entity. + + Expected Behavior: + Gradient Generator components are incompatible with Vegetation area components. + + Test Steps: + 1) Create a new level + 2) Create a new entity in the level + 3) Add each Gradient Generator component to an entity, and add a Vegetation Area component to the same entity + 4) Verify that components are only enabled when entity is free of a conflicting component + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. :return: None """ diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py index b7d12d074a..f2edc2924e 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py @@ -28,8 +28,21 @@ class TestGradientModifiersIncompatibilities(EditorTestHelper): def run_test(self): """ Summary: - Verify that Entities are not active when a Gradient Modifier and incompatible component are both present - on the same Entity. + This test verifies that components are disabled when conflicting components are present on the same entity. + + Expected Behavior: + Gradient Modifier components are incompatible with Vegetation area components. + + Test Steps: + 1) Create a new level + 2) Create a new entity in the level + 3) Add each Gradient Modifier component to an entity, and add a Vegetation Area component to the same entity + 4) Verify that components are only enabled when entity is free of a conflicting component + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. :return: None """ diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py index c37ee36265..45da74d6cd 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py @@ -9,19 +9,6 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. """ -""" -The below cases are combined in this script -C2676829 -C3961326 -C3980659 -C3980664 -C3980669 -C3416548 -C2676823 -C3961321 -C2676826 -""" - import os import sys diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py index d1e0b68ef4..c41d153cfa 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py @@ -33,6 +33,26 @@ class TestAreaNodeComponentDependency(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="AreaNodeComponentDependency", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities with + proper dependent components. + + Expected Behavior: + All expected component dependencies are met when adding an area node to a graph. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Drag each of the area nodes to the graph area, and ensure the proper dependent components are added + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global newEntityId diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py index 4e429a192b..fb977b4987 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py @@ -33,7 +33,25 @@ class TestGradientNodeEntityCreate(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="AreaNodeEntityCreate", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities. + Expected Behavior: + New entities are created when dragging area nodes to graph area. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Drag each of the area nodes to the graph area, and ensure a new entity is created + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global newEntityId newEntityId = parameters[0] diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityRemovedOnNodeDelete.py index 38f8641b4c..57ba8fc006 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityRemovedOnNodeDelete.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityRemovedOnNodeDelete.py @@ -34,7 +34,26 @@ class TestAreaNodeEntityDelete(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="AreaNodeEntityDelete", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor. + Expected Behavior: + Entities are removed when area nodes are deleted from a graph. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Drag each of the area nodes to the graph area, and ensure a new entity is created + 4) Delete the nodes, and ensure the newly created entities are removed + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global createdEntityId createdEntityId = parameters[0] diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py index 26062c01f8..60527b64d2 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py @@ -9,24 +9,6 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. """ - -""" -C22602072 - Graph is updated when underlying components are added/removed - -1. Open Level. -2. Find LandscapeCanvas named entity. -3. Ensure Vegetation Distribution Component is present on the BushSpawner entity. -4. Open graph and ensure Distribution Filter wrapped node is present. -5. Delete the Vegetation Distribution Filter component from the BushSpawner entity via Entity Inspector. -6. Ensure the Vegetation Distribution Filter component was deleted from the BushSpawner entity and node is no longer -present in the graph. -7. Add Vegetation Altitude Filter to the BushSpawner entity through Entity Inspector. -8. Ensure Altitude Filter was added to the BushSpawner node in the open graph. -9. Add a new entity with unique name as a child of the Landscape Canvas entity. -10. Add a Box Shape component to the new child entity. -11. Ensure Box Shape node is present on the open graph. -""" - import os import sys @@ -50,6 +32,36 @@ class TestComponentUpdatesUpdateGraph(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="ComponentUpdatesUpdateGraph", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that the Landscape Canvas graphs update properly when components are added/removed outside of + Landscape Canvas. + + Expected Behavior: + Graphs properly reflect component changes made to entities outside of Landscape Canvas. + + Test Steps: + 1. Open Level + 2. Find LandscapeCanvas named entity + 3. Ensure Vegetation Distribution Component is present on the BushSpawner entity + 4. Open graph and ensure Distribution Filter wrapped node is present + 5. Delete the Vegetation Distribution Filter component from the BushSpawner entity via Entity Inspector + 6. Ensure the Vegetation Distribution Filter component was deleted from the BushSpawner entity and node is + no longer present in the graph + 7. Add Vegetation Altitude Filter to the BushSpawner entity through Entity Inspector + 8. Ensure Altitude Filter was added to the BushSpawner node in the open graph + 9. Add a new entity with unique name as a child of the Landscape Canvas entity + 10. Add a Box Shape component to the new child entity + 11. Ensure Box Shape node is present on the open graph + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ + # Create a new empty level and instantiate LC_BushFlowerBlender.slice self.test_success = self.create_level( self.args["level"], diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py index 5fed13985d..4b5e03abbc 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py @@ -37,6 +37,25 @@ class TestCreateNewGraph(EditorTestHelper): print("New root entity created") def run_test(self): + """ + Summary: + This test verifies that new graphs can be created in Landscape Canvas. + + Expected Behavior: + New graphs can be created, and proper entity is created to hold graph data with a Landscape Canvas component. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Ensures the root entity created contains a Landscape Canvas component + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ self.test_success = self.create_level( self.args["level"], heightmap_resolution=128, diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py index 7fd3f075e0..81e24b20e1 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py @@ -33,7 +33,25 @@ class TestDisabledNodeDuplication(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="DisabledNodeDuplication", args=["level"]) def run_test(self): + """ + Summary: + This test verifies Editor stability after duplicating disabled Landscape Canvas nodes. + Expected Behavior: + Editor remains stable and free of crashes. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Create several new nodes, disable the nodes via disabling/deleting components, and duplicate the nodes + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global newEntityId newEntityId = parameters[0] diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py index 27ab6fded3..61c4cf9ac2 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py @@ -9,17 +9,6 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. """ - -""" -C30813586 - Editor remains stable after Undoing deletion of a node on a slice entity - -1. Open level with instantiated slice. -2. Open the graph. -3. Find the BushSpawner's Vegetation Layer Spawner node. -4. Delete the node. -5. Undo to restore the node. -""" - import os import sys @@ -44,7 +33,26 @@ class TestUndoNodeDeleteSlice(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="UndoNodeDeleteSlice", args=["level"]) def run_test(self): + """ + Summary: + This test verifies Editor stability after undoing the deletion of nodes on a slice entity. + Expected Behavior: + Editor remains stable and free of crashes. + + Test Steps: + 1) Create a new level + 2) Instantiate a slice with a Landscape Canvas setup + 3) Find a specific node on the graph, and delete it + 4) Restore the node with Undo + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ # Create a new empty level and instantiate LC_BushFlowerBlender.slice self.test_success = self.create_level( self.args["level"], diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py index ca3bc04f47..124baf9d2e 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py @@ -34,6 +34,27 @@ class TestGradientMixerNodeConstruction(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="GradientMixerNodeConstruction", args=["level"]) def run_test(self): + """ + Summary: + This test verifies a Gradient Mixer vegetation setup can be constructed through Landscape Canvas. + + Expected Behavior: + Entities contain all required components and component references after creating nodes and setting connections + on a Landscape Canvas graph. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Add all necessary nodes to the graph and set connections to form a Gradient Mixer setup + 4) Verify all components and component references were properly set during graph construction + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global newEntityId diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py index d40b19e7db..aa98eb3dc3 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py @@ -33,6 +33,25 @@ class TestGradientModifierNodeEntityCreate(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="GradientModifierNodeEntityCreate", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities. + + Expected Behavior: + New entities are created when dragging Gradient Modifier nodes to graph area. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Drag each of the Gradient Modifier nodes to the graph area, and ensure a new entity is created + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global newEntityId diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py index dc263924d1..6a82b05039 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py @@ -34,7 +34,26 @@ class TestGradientModifierNodeEntityDelete(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="GradientModifierNodeEntityDelete", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor. + Expected Behavior: + Entities are removed when Gradient Modifier nodes are deleted from a graph. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Drag each of the Gradient Modifier nodes to the graph area, and ensure a new entity is created + 4) Delete the nodes, and ensure the newly created entities are removed + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global createdEntityId createdEntityId = parameters[0] diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py index 5e203e1892..f9360fe356 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py @@ -33,6 +33,27 @@ class TestGradientNodeComponentDependency(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="GradientNodeComponentDependency", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities with + proper dependent components. + + Expected Behavior: + All expected component dependencies are met when adding a Gradient Modifier node to a graph. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Drag each of the Gradient Modifier nodes to the graph area, and ensure the proper dependent components are + added + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global newEntityId diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py index 6d4a2f58a7..8aaad9b81d 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py @@ -32,6 +32,25 @@ class TestGradientNodeEntityCreate(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="GradientNodeEntityCreate", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities. + + Expected Behavior: + New entities are created when dragging Gradient nodes to graph area. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Drag each of the Gradient nodes to the graph area, and ensure a new entity is created + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global newEntityId diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py index 2b49e3a911..d74b86d0bf 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py @@ -34,6 +34,26 @@ class TestGradientNodeEntityDelete(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="GradientNodeEntityDelete", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor. + + Expected Behavior: + Entities are removed when Gradient nodes are deleted from a graph. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Drag each of the Gradient nodes to the graph area, and ensure a new entity is created + 4) Delete the nodes, and ensure the newly created entities are removed + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global createdEntityId diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py index d3ad5c1c1e..6aa539b554 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py @@ -31,6 +31,26 @@ class TestGraphClosedOnEntityDelete(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="GraphClosedOnEntityDelete", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that Landscape Canvas graphs are auto-closed when the corresponding entity is deleted. + + Expected Behavior: + When a Landscape Canvas root entity is deleted, the corresponding graph automatically closes. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Delete the automatically created entity + 4) Verify the open graph is closed + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global newRootEntityId diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py index b7b0008eb2..ebc75ab621 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py @@ -29,7 +29,26 @@ class TestGraphClosedOnLevelChange(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="GraphClosedOnLevelChange", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that Landscape Canvas graphs are auto-closed when the currently open level changes. + Expected Behavior: + When a new level is loaded in the Editor, open Landscape Canvas graphs are automatically closed. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Open a different level + 4) Verify the open graph is closed + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ # Create a new empty level self.test_success = self.create_level( self.args["level"], diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py index efd1cc5a55..4b018aeb45 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py @@ -29,6 +29,26 @@ class TestGraphClosedTabbedGraph(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="GraphClosedTabbedGraph", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that Landscape Canvas tabbed graphs can be independently closed. + + Expected Behavior: + Closing a tabbed graph only closes the appropriate graph. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create several new graphs + 3) Close one of the open graphs + 4) Ensure the graph properly closed, and other open graphs remain open + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ # Create a new empty level self.test_success = self.create_level( diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py index f350d37178..f94a6c2e3a 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py @@ -9,21 +9,6 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. """ - -""" -C22715182 - Components are updated when nodes are added/removed/updated - -1. Open Level. -2. Open the graph on LC_BushFlowerBlender.slice -3. Find the Rotation Modifier node on the BushSpawner entity -4. Delete the Rotation Modifier node -5. Ensure the Vegetation Rotation Modifier component is removed from the BushSpawner entity -6. Delete the Vegetation Layer Spawner node from the graph -7. Ensure BushSpawner entity is deleted -8. Change connection from second Rotation Modifier node to a different Gradient -9. Ensure Gradient reference on component is updated -""" - import os import sys @@ -50,6 +35,31 @@ class TestGraphUpdatesUpdateComponents(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="GraphUpdatesUpdateComponents", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that components are properly updated as nodes are added/removed/updated. + + Expected Behavior: + Landscape Canvas node CRUD properly updates component entities. + + Test Steps: + 1. Open Level. + 2. Open the graph on LC_BushFlowerBlender.slice + 3. Find the Rotation Modifier node on the BushSpawner entity + 4. Delete the Rotation Modifier node + 5. Ensure the Vegetation Rotation Modifier component is removed from the BushSpawner entity + 6. Delete the Vegetation Layer Spawner node from the graph + 7. Ensure BushSpawner entity is deleted + 8. Change connection from second Rotation Modifier node to a different Gradient + 9. Ensure Gradient reference on component is updated + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ # Create a new empty level and instantiate LC_BushFlowerBlender.slice self.test_success = self.create_level( self.args["level"], diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py index 176429885f..c3857e1393 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py @@ -30,6 +30,26 @@ class TestLandscapeCanvasComponentAddedRemoved(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="LandscapeCanvasComponentAddedRemoved", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that the Landscape Canvas component can be added to/removed from an entity. + + Expected Behavior: + Closing a tabbed graph only closes the appropriate graph. + + Test Steps: + 1) Create a new level + 2) Create a new entity + 3) Add a Landscape Canvas component to the entity + 4) Remove the Landscape Canvas component from the entity + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ # Create a new empty level self.test_success = self.create_level( diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py index e0f13adaa9..f174a52610 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py @@ -30,12 +30,21 @@ class TestLandscapeCanvasSliceCreateInstantiate(EditorTestHelper): def run_test(self): """ Summary: - C22602016 A slice containing the LandscapeCanvas component can be created/instantiated. + A slice containing the LandscapeCanvas component can be created/instantiated. Expected Result: - Slice is created and processed successfully and free of errors/warnings. - Another copy of the slice is instantiated. + Slice is created/processed/instantiated successfully and free of errors/warnings. + Test Steps: + 1) Create a new level + 2) Create a new entity with a Landscape Canvas component + 3) Create a slice of the new entity + 4) Instantiate a new copy of the slice + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. :return: None """ diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py index ecc529b9b4..82a2abf5ea 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py @@ -34,6 +34,27 @@ class TestLayerBlenderNodeConstruction(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="LayerBlenderNodeConstruction", args=["level"]) def run_test(self): + """ + Summary: + This test verifies a Layer Blender vegetation setup can be constructed through Landscape Canvas. + + Expected Behavior: + Entities contain all required components and component references after creating nodes and setting connections + on a Landscape Canvas graph. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Add all necessary nodes to the graph and set connections to form a Layer Blender setup + 4) Verify all components and component references were properly set during graph construction + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global newEntityId diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py index 00fcb5170c..df3c549fff 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py @@ -34,6 +34,25 @@ class TestLayerExtenderNodeComponentEntitySync(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="LayerExtenderNodeComponentEntitySync", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that all wrapped nodes can be successfully added to/removed from parent nodes. + + Expected Behavior: + All wrapped extender nodes can be added to/removed from appropriate parent nodes. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Add Area Blender and Layer Spawner nodes to the graph, and add/remove each extender node to/from each + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global newEntityId diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py index bd10e5f4c6..cd4915ea24 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py @@ -33,6 +33,25 @@ class TestShapeNodeEntityCreate(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="ShapeNodeEntityCreate", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities. + + Expected Behavior: + New entities are created when dragging shape nodes to graph area. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Drag each of the shape nodes to the graph area, and ensure a new entity is created + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ def onEntityCreated(parameters): global newEntityId diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py index f71f5ae906..fcfbe03576 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py @@ -34,7 +34,27 @@ class TestShapeNodeEntityDelete(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="ShapeNodeEntityDelete", args=["level"]) def run_test(self): - + """ + Summary: + This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor. + + Expected Behavior: + Entities are removed when shape nodes are deleted from a graph. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Drag each of the shape nodes to the graph area, and ensure a new entity is created + 4) Delete the nodes, and ensure the newly created entities are removed + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ + def onEntityCreated(parameters): global createdEntityId createdEntityId = parameters[0] diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py index 968f39c64d..183c3f7ccb 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py @@ -33,6 +33,27 @@ class TestSlotConnectionsUpdateComponents(EditorTestHelper): EditorTestHelper.__init__(self, log_prefix="SlotConnectionsUpdateComponents", args=["level"]) def run_test(self): + """ + Summary: + This test verifies that the Landscape Canvas slot connections properly update component references. + + Expected Behavior: + A reference created through slot connections in Landscape Canvas is reflected in the Entity Inspector. + + Test Steps: + 1) Create a new level + 2) Open Landscape Canvas and create a new graph + 3) Several nodes are added to a graph, and connections are set between the nodes + 4) Component references are verified via Entity Inspector + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. + + :return: None + """ + # Retrieve the proper component TypeIds per component name componentNames = [ 'Random Noise Gradient', From 5fa67c23db520a88b667b14ac4f3b04317517193 Mon Sep 17 00:00:00 2001 From: jckand-amzn Date: Wed, 26 May 2021 17:18:29 -0500 Subject: [PATCH 08/41] SPEC-6685: Adding/updating more test summaries for TestRail decoupling effort --- ...tPreviewSettings_DefaultPinnedEntityIsSelf.py | 16 +++++++++++++++- ...entSurfaceTagEmitter_ComponentDependencies.py | 16 +++++++++++++--- .../GradientTransform_RequiresShape.py | 16 ++++++++++++++-- .../EditorScripts/ImageGradient_RequiresShape.py | 16 ++++++++++++++-- 4 files changed, 56 insertions(+), 8 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py index 5a758b9d89..b8f4114d30 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py @@ -44,7 +44,21 @@ class TestGradientPreviewSettings(EditorTestHelper): def run_test(self): """ Summary: - Verify if the current entity is set to the pin preview to shape entity by default for several components. + This test verifies default values for the pinned entity for Gradient Preview settings. + + Expected Behavior: + Pinned entity is self for all gradient generator/modifiers. + + Test Steps: + 1) Create a new level + 2) Create a new entity in the level + 3) Add each Gradient Generator component to an entity, and verify the Pin Preview to Shape property is set to + self + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. :return: None """ diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py index a16e37e0fc..8e2d0611af 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py @@ -31,11 +31,21 @@ class TestGradientSurfaceTagEmitterDependencies(EditorTestHelper): def run_test(self): """ Summary: - Component has a dependency on a Gradient component + This test verifies that the Gradient Surface Tag Emitter component is dependent on a gradient component. Expected Result: - Component is disabled until a Gradient Generator, Modifier or Gradient Reference component - (and any sub-dependencies) is added to the entity. + Gradient Surface Tag Emitter component is disabled until a Gradient Generator, Modifier or Gradient Reference + component (and any sub-dependencies) is added to the entity. + + Test Steps: + 1) Open level + 2) Create a new entity with a Gradient Surface Tag Emitter component + 3) Verify the component is disabled until a dependent component is also added to the entity + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. :return: None """ diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py index e1e901f2f7..2311363db9 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py @@ -28,8 +28,20 @@ class TestGradientTransformRequiresShape(EditorTestHelper): def run_test(self): """ Summary: - Verify that Gradient Transform Modifier component requires a - Shape component before the Entity can become active. + This test verifies that the Gradient Transform Modifier component is dependent on a shape component. + + Expected Result: + Gradient Transform Modifier component is disabled until a shape component is added to the entity. + + Test Steps: + 1) Open level + 2) Create a new entity with a Gradient Transform Modifier component + 3) Verify the component is disabled until a shape component is also added to the entity + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. :return: None """ diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py index dab8e6928a..a5d9632fd6 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py @@ -28,8 +28,20 @@ class TestImageGradientRequiresShape(EditorTestHelper): def run_test(self): """ Summary: - Verify that Image Gradient component requires a - Shape component before the Entity can become active. + This test verifies that the Image Gradient component is dependent on a shape component. + + Expected Result: + Gradient Transform Modifier component is disabled until a shape component is added to the entity. + + Test Steps: + 1) Open level + 2) Create a new entity with a Image Gradient component + 3) Verify the component is disabled until a shape component is also added to the entity + + Note: + - This test file must be called from the Open 3D Engine Editor command terminal + - Any passed and failed tests are written to the Editor.log file. + Parsing the file or running a log_monitor are required to observe the test results. :return: None """ From 2ba645c2649914750156b577f3cd5fd2d30119d5 Mon Sep 17 00:00:00 2001 From: scottr Date: Wed, 26 May 2021 16:13:14 -0700 Subject: [PATCH 09/41] [cpack_installer] post install hooks to install cmake and python --- cmake/LYWrappers.cmake | 3 +- cmake/Platform/Common/Install_common.cmake | 2 +- .../Windows/Packaging/PostInstallSetup.wxs | 67 +++++++++++++ .../Windows/Packaging/Template.wxs.in | 19 +++- .../Platform/Windows/Packaging_windows.cmake | 5 + scripts/setup.bat | 93 ------------------- 6 files changed, 92 insertions(+), 97 deletions(-) create mode 100644 cmake/Platform/Windows/Packaging/PostInstallSetup.wxs delete mode 100644 scripts/setup.bat diff --git a/cmake/LYWrappers.cmake b/cmake/LYWrappers.cmake index f6a36afc89..2f8349c840 100644 --- a/cmake/LYWrappers.cmake +++ b/cmake/LYWrappers.cmake @@ -334,7 +334,8 @@ function(ly_add_target) if(NOT ly_add_target_IMPORTED) if(NOT ly_add_target_INSTALL_COMPONENT) - set(ly_add_target_INSTALL_COMPONENT ${LY_DEFAULT_INSTALL_COMPONENT}) + #set(ly_add_target_INSTALL_COMPONENT ${LY_DEFAULT_INSTALL_COMPONENT}) + set(ly_add_target_INSTALL_COMPONENT ${ly_add_target_NAMESPACE}) endif() ly_install_target( diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 8fe2fe2c1c..46d23f7b91 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -286,7 +286,7 @@ endfunction() function(ly_setup_others) # List of directories we want to install relative to engine root - set(DIRECTORIES_TO_INSTALL Tools/LyTestTools Tools/RemoteConsole) + set(DIRECTORIES_TO_INSTALL Tools/LyTestTools Tools/RemoteConsole Tools/Redistributables/CMake) foreach(dir ${DIRECTORIES_TO_INSTALL}) get_filename_component(install_path ${dir} DIRECTORY) diff --git a/cmake/Platform/Windows/Packaging/PostInstallSetup.wxs b/cmake/Platform/Windows/Packaging/PostInstallSetup.wxs new file mode 100644 index 0000000000..ebcaa9502f --- /dev/null +++ b/cmake/Platform/Windows/Packaging/PostInstallSetup.wxs @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmake/Platform/Windows/Packaging/Template.wxs.in b/cmake/Platform/Windows/Packaging/Template.wxs.in index 2900b96f41..e14e064fbc 100644 --- a/cmake/Platform/Windows/Packaging/Template.wxs.in +++ b/cmake/Platform/Windows/Packaging/Template.wxs.in @@ -17,8 +17,7 @@ - @@ -41,8 +40,24 @@ + + + + + + + NOT Installed Or REINSTALL + + + NOT Installed Or REINSTALL + + + NOT Installed Or REINSTALL + + + diff --git a/cmake/Platform/Windows/Packaging_windows.cmake b/cmake/Platform/Windows/Packaging_windows.cmake index ce73e9a07b..b7db250fda 100644 --- a/cmake/Platform/Windows/Packaging_windows.cmake +++ b/cmake/Platform/Windows/Packaging_windows.cmake @@ -83,9 +83,14 @@ set(CPACK_WIX_PRODUCT_ICON ${CPACK_SOURCE_DIR}/Platform/Windows/Packaging/produc set(CPACK_WIX_TEMPLATE "${CPACK_SOURCE_DIR}/Platform/Windows/Packaging/Template.wxs.in") set(CPACK_WIX_EXTRA_SOURCES + "${CPACK_SOURCE_DIR}/Platform/Windows/Packaging/PostInstallSetup.wxs" "${CPACK_SOURCE_DIR}/Platform/Windows/Packaging/Shortcuts.wxs" ) +set(CPACK_WIX_EXTENSIONS + WixUtilExtension +) + set(_embed_artifacts "yes") if(LY_INSTALLER_DOWNLOAD_URL) diff --git a/scripts/setup.bat b/scripts/setup.bat deleted file mode 100644 index 34251ad861..0000000000 --- a/scripts/setup.bat +++ /dev/null @@ -1,93 +0,0 @@ -@echo off -rem -rem All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -rem its licensors. -rem -rem For complete copyright and license terms please see the LICENSE at the root of this -rem distribution (the "License"). All use of this software is governed by the License, -rem or, if provided, by the license below or the license accompanying this file. Do not -rem remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -rem - -pushd %~dp0% - -pushd %~dp0.. -set ENGINE_ROOT=%CD% -popd - -set cmake_version=3.19.1 - -if not "%1"=="" ( - set LY_3RDPARTY_PATH=%1 -) -if "%LY_3RDPARTY_PATH%"=="" goto no_3rd_party - -if not exist %LY_3RDPARTY_PATH% mkdir %LY_3RDPARTY_PATH% -goto install_cmake - -:no_3rd_party -echo A path to where the 3rd party folder is required for setup. -echo Either supply one through the LY_3RDPARTY_PATH environment -echo variable or as an argument to this script -goto fail - - -:install_cmake -set cmake_install_path=%LY_3RDPARTY_PATH%\CMake\%cmake_version%\Windows -set cmake_archive_name=cmake-%cmake_version%-win64-x64 -set cmake_archive_path="%ENGINE_ROOT%\Tools\Redistributables\CMake\%cmake_archive_name%.zip" -if exist "%cmake_install_path%\bin\cmake.exe" goto install_python - -echo Installing CMake %cmake_version% to %cmake_install_path% -if not exist %cmake_install_path% mkdir %cmake_install_path% -powershell.exe -nologo -noprofile -command^ - "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('%cmake_archive_path%', '%cmake_install_path%'); }" -if ERRORLEVEL 1 goto cmake_failed - -set cmake_extracted_path=%cmake_install_path%\%cmake_archive_name% -for /d %%a in ("%cmake_extracted_path%\*") do move "%%a" "%cmake_install_path%\" -rmdir %cmake_extracted_path% - -goto success - -if ERRORLEVEL 1 goto cmake_failed -set LY_CMAKE_PATH="%cmake_install_path%\bin" -goto install_python - -:cmake_failed -echo Failed to extract cmake to path %cmake_install_path% -goto fail - - -:install_python -echo Installing python... -call %ENGINE_ROOT%\python\get_python.bat -if ERRORLEVEL 1 goto python_failed -goto register_engine - -:python_failed -echo Failed to acquire python -goto fail - - -:register_engine -echo Registering engine... -call %ENGINE_ROOT%\scripts\o3de.bat register --this-engine -if ERRORLEVEL 1 goto registration_failed -goto success - -:registration_failed -echo Failed to register the engine -goto fail - - -:fail -echo O3DE setup failed -popd -exit /b 1 - -:success -echo O3DE setup complete -popd -exit /b %ERRORLEVEL% From cccb68fa38e479b1d0aa851718620384ff483ff2 Mon Sep 17 00:00:00 2001 From: scottr Date: Wed, 26 May 2021 16:21:04 -0700 Subject: [PATCH 10/41] [cpack_installer] revert accidental debug change committed --- cmake/LYWrappers.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/LYWrappers.cmake b/cmake/LYWrappers.cmake index f7290009de..8aba6ccb99 100644 --- a/cmake/LYWrappers.cmake +++ b/cmake/LYWrappers.cmake @@ -339,8 +339,7 @@ function(ly_add_target) if(NOT ly_add_target_IMPORTED) if(NOT ly_add_target_INSTALL_COMPONENT) - #set(ly_add_target_INSTALL_COMPONENT ${LY_DEFAULT_INSTALL_COMPONENT}) - set(ly_add_target_INSTALL_COMPONENT ${ly_add_target_NAMESPACE}) + set(ly_add_target_INSTALL_COMPONENT ${LY_DEFAULT_INSTALL_COMPONENT}) endif() ly_install_target( From 78616a7befd66119514d02c6c738b45fad731b3b Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Wed, 26 May 2021 16:21:52 -0700 Subject: [PATCH 11/41] Updated test materials to force UV center back to (0,0) since the default is now (0.5,0.5). This gets the screenshot tests in ASV working again. --- .../001_ManyFeatures.material | 8 ++++++++ .../005_UseDisplacement.material | 12 +++++++----- .../012_Parallax_POM_Cutout.material | 5 ++++- .../101_DetailMaps_LucyBaseNoDetailMaps.material | 14 ++++++++++---- .../102_DetailMaps_All.material | 14 +++++++++----- ...105_DetailMaps_BlendMaskUsingDetailUVs.material | 14 +++++++++----- 6 files changed, 47 insertions(+), 20 deletions(-) diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material index 1c02f56af6..415bd36dcf 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material @@ -86,6 +86,10 @@ "textureMap": "TestData/Textures/cc0/Lava004_1K_Roughness.jpg" }, "layer2_uv": { + "center": [ + 0.0, + 0.0 + ], "offsetU": 0.5, "offsetV": 0.25 }, @@ -128,6 +132,10 @@ "factor": 0.47474750876426699 }, "layer3_uv": { + "center": [ + 0.0, + 0.0 + ], "offsetU": 0.11999999731779099, "rotateDegrees": -57.599998474121097 }, diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material index 55a4774d49..9163fe0a0c 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material @@ -46,8 +46,8 @@ }, "layer2_uv": { "center": [ - 0.5, - 0.5 + 0.0, + 0.0 ], "offsetU": 0.1599999964237213, "offsetV": 0.07999999821186066, @@ -67,13 +67,15 @@ "textureMap": "TestData/Textures/cc0/Rocks002_1K_Roughness.jpg" }, "layer3_uv": { + "center": [ + 0.0, + 0.0 + ], "scale": 3.4999988079071047 }, "parallax": { "algorithm": "Relief", - "enable": true, - "pdo": true, - "quality": "Low" + "pdo": true } } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material index fb862dc5d3..21f873fe1a 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material @@ -13,13 +13,16 @@ "textureMap": "TestData/Textures/checker8x8_512.png" }, "parallax": { - "algorithm": "POM", "enable": true, "factor": 0.10000000149011612, "quality": "High", "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_disp.png" }, "uv": { + "center": [ + 0.0, + 0.0 + ], "scale": 0.5 } } diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/101_DetailMaps_LucyBaseNoDetailMaps.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/101_DetailMaps_LucyBaseNoDetailMaps.material index 7b1f0ba6a9..6d77be5a49 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/101_DetailMaps_LucyBaseNoDetailMaps.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/101_DetailMaps_LucyBaseNoDetailMaps.material @@ -8,18 +8,24 @@ "textureMap": "Objects/Lucy/Lucy_bronze_BaseColor.png", "textureMapUv": "Unwrapped" }, + "detailUV": { + "center": [ + 0.0, + 0.0 + ] + }, "metallic": { - "textureMap": "Objects/Lucy/Lucy_bronze_metallic.png", + "textureMap": "Objects/Lucy/Lucy_bronze_Metallic.png", "textureMapUv": "Unwrapped" }, "normal": { "flipY": true, - "textureMap": "Objects/Lucy/Lucy_normal.png", + "textureMap": "Objects/Lucy/Lucy_Normal.png", "textureMapUv": "Unwrapped" }, "roughness": { - "textureMap": "Objects/Lucy/Lucy_bronze_roughness.png", + "textureMap": "Objects/Lucy/Lucy_bronze_Roughness.png", "textureMapUv": "Unwrapped" } } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/102_DetailMaps_All.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/102_DetailMaps_All.material index 55a01866b5..1a29f392c8 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/102_DetailMaps_All.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/102_DetailMaps_All.material @@ -5,7 +5,7 @@ "propertyLayoutVersion": 3, "properties": { "baseColor": { - "textureMap": "Objects/Lucy/Lucy_bronze_baseColor.png", + "textureMap": "Objects/Lucy/Lucy_bronze_BaseColor.png", "textureMapUv": "Unwrapped" }, "detailLayerGroup": { @@ -19,20 +19,24 @@ "normalDetailStrength": 1.5 }, "detailUV": { + "center": [ + 0.0, + 0.0 + ], "scale": 10.0 }, "metallic": { - "textureMap": "Objects/Lucy/Lucy_bronze_metallic.png", + "textureMap": "Objects/Lucy/Lucy_bronze_Metallic.png", "textureMapUv": "Unwrapped" }, "normal": { "flipY": true, - "textureMap": "Objects/Lucy/Lucy_normal.png", + "textureMap": "Objects/Lucy/Lucy_Normal.png", "textureMapUv": "Unwrapped" }, "roughness": { - "textureMap": "Objects/Lucy/Lucy_bronze_roughness.png", + "textureMap": "Objects/Lucy/Lucy_bronze_Roughness.png", "textureMapUv": "Unwrapped" } } -} +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/105_DetailMaps_BlendMaskUsingDetailUVs.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/105_DetailMaps_BlendMaskUsingDetailUVs.material index 6193cf4eed..a69b72b623 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/105_DetailMaps_BlendMaskUsingDetailUVs.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/105_DetailMaps_BlendMaskUsingDetailUVs.material @@ -5,7 +5,7 @@ "propertyLayoutVersion": 3, "properties": { "baseColor": { - "textureMap": "Objects/Lucy/Lucy_bronze_baseColor.png", + "textureMap": "Objects/Lucy/Lucy_bronze_BaseColor.png", "textureMapUv": "Unwrapped" }, "detailLayerGroup": { @@ -18,20 +18,24 @@ "normalDetailStrength": 1.5 }, "detailUV": { + "center": [ + 0.0, + 0.0 + ], "scale": 10.0 }, "metallic": { - "textureMap": "Objects/Lucy/Lucy_bronze_metallic.png", + "textureMap": "Objects/Lucy/Lucy_bronze_Metallic.png", "textureMapUv": "Unwrapped" }, "normal": { "flipY": true, - "textureMap": "Objects/Lucy/Lucy_normal.png", + "textureMap": "Objects/Lucy/Lucy_Normal.png", "textureMapUv": "Unwrapped" }, "roughness": { - "textureMap": "Objects/Lucy/Lucy_bronze_roughness.png", + "textureMap": "Objects/Lucy/Lucy_bronze_Roughness.png", "textureMapUv": "Unwrapped" } } -} +} \ No newline at end of file From 79d66dd492b90ec17233f1beff1972b649ec8e28 Mon Sep 17 00:00:00 2001 From: sweeneys Date: Wed, 26 May 2021 16:22:32 -0700 Subject: [PATCH 12/41] Search for external project definition before searching for internal projects --- .../managers/abstract_resource_locator.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py b/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py index 5a14ef9419..ec4b43b023 100755 --- a/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py +++ b/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py @@ -16,8 +16,10 @@ import pathlib import warnings from abc import ABCMeta, abstractmethod +import ly_test_tools._internal.pytest_plugin from ly_test_tools.environment.file_system import find_ancestor_file + def _find_engine_root(initial_path): # type: (str) -> str """ @@ -34,11 +36,9 @@ def _find_engine_root(initial_path): # Assumes folder structure similar to: engine_root/dev/Tools/.../ly_test_tools/builtin for _ in range(15): if os.path.exists(os.path.join(current_dir, root_file)): - # The parent of the directory containing the engineroot.txt is the root directory - engine_root = current_dir - return engine_root - # Using an explicit else to avoid aberrant behavior from following filesystem links - else: + # parent of the directory containing root_file + return current_dir + else: # explicit else avoids aberrant behavior from following filesystem links current_dir = os.path.abspath(os.path.join(current_dir, os.path.pardir)) raise OSError(f"Unable to find engine root directory. Verify root file '{root_file}' exists") @@ -50,8 +50,10 @@ def _find_project_json(engine_root, project): Find the project.json file for this project. :return: Full path to the project.json file """ - project_json = find_ancestor_file('project.json') - if not project_json: + # First check relative to defined build directory, for external projects which configure through SDK settings + project_json = find_ancestor_file(target_file_name='project.json', + start_path=ly_test_tools._internal.pytest_plugin.build_directory) + if not project_json: # check internally for a project bundled with the engine project_json = os.path.join(engine_root, project, 'project.json') return project_json From 883ddf667e70fe61491dcc2a7162e59bc5d46166 Mon Sep 17 00:00:00 2001 From: scottr Date: Wed, 26 May 2021 20:19:42 -0700 Subject: [PATCH 13/41] [cpack_installer] removed static cmake package in favor of using file(DOWNLOAD ...) --- .../CMake/cmake-3.19.1-win64-x64.zip | 3 -- cmake/Packaging.cmake | 37 +++++++++++++++++++ cmake/Platform/Common/Install_common.cmake | 2 +- .../Windows/Packaging/PostInstallSetup.wxs | 6 +-- .../Platform/Windows/Packaging_windows.cmake | 5 +++ 5 files changed, 45 insertions(+), 8 deletions(-) delete mode 100644 Tools/Redistributables/CMake/cmake-3.19.1-win64-x64.zip diff --git a/Tools/Redistributables/CMake/cmake-3.19.1-win64-x64.zip b/Tools/Redistributables/CMake/cmake-3.19.1-win64-x64.zip deleted file mode 100644 index fc3a243f06..0000000000 --- a/Tools/Redistributables/CMake/cmake-3.19.1-win64-x64.zip +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e95d70549f306adb46e0f131dcecdbcbc6412d3a1e073c2c0078812391bf21d3 -size 36098689 diff --git a/cmake/Packaging.cmake b/cmake/Packaging.cmake index fbeffa94eb..7766d7d0ee 100644 --- a/cmake/Packaging.cmake +++ b/cmake/Packaging.cmake @@ -17,6 +17,8 @@ endif() set(LY_INSTALLER_DOWNLOAD_URL "" CACHE STRING "URL embedded into the installer to download additional artifacts") set(LY_INSTALLER_LICENSE_URL "" CACHE STRING "Optionally embed a link to the license instead of raw text") +set(CPACK_DESIRED_CMAKE_VERSION 3.20.2) + # set all common cpack variable overrides first so they can be accessible via configure_file # when the platform specific settings are applied below. additionally, any variable with # the "CPACK_" prefix will automatically be cached for use in any phase of cpack namely @@ -38,6 +40,7 @@ set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_VENDOR}/${CPACK_PACKAGE_VER # neither of the SOURCE_DIR variables equate to anything during execution of pre/post build scripts set(CPACK_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +set(CPACK_BINARY_DIR ${CMAKE_BINARY_DIR}/_CPack) # to match other CPack out dirs # attempt to apply platform specific settings ly_get_absolute_pal_filename(pal_dir ${CPACK_SOURCE_DIR}/Platform/${PAL_HOST_PLATFORM_NAME}) @@ -48,6 +51,40 @@ if(NOT CPACK_GENERATOR) return() endif() +# pull down the desired copy of CMake so it can be included in the package +if(NOT (CPACK_CMAKE_PACKAGE_FILE AND CPACK_CMAKE_PACKAGE_HASH)) + message(FATAL_ERROR + "Packaging is missing one or more following properties required to include CMake: " + " CPACK_CMAKE_PACKAGE_FILE, CPACK_CMAKE_PACKAGE_HASH") +endif() + +set(_cmake_package_dest ${CPACK_BINARY_DIR}/${CPACK_CMAKE_PACKAGE_FILE}) + +string(REPLACE "." ";" _version_componets "${CPACK_DESIRED_CMAKE_VERSION}") +list(GET _version_componets 0 _major_version) +list(GET _version_componets 1 _minor_version) + +set(_url_version_tag "v${_major_version}.${_minor_version}") + +message(STATUS "Ensuring CMake ${CPACK_DESIRED_CMAKE_VERSION} is avaiable for packaging...") +file(DOWNLOAD + https://cmake.org/files/${_url_version_tag}/${CPACK_CMAKE_PACKAGE_FILE} + ${_cmake_package_dest} +) + +file(SHA256 ${_cmake_package_dest} _package_hash) +if (NOT "${_package_hash}" STREQUAL "${CPACK_CMAKE_PACKAGE_HASH}") + file(REMOVE ${_cmake_package_dest}) + message(FATAL_ERROR "Donwload package of CMake does not match expected hash value. " + "Please double check the properies CPACK_CMAKE_PACKAGE_FILE and CPACK_CMAKE_PACKAGE_HASH " + "before trying again.") +endif() + +install(FILES ${_cmake_package_dest} + DESTINATION ./Tools/Redistributables/CMake + COMPONENT ${LY_DEFAULT_INSTALL_COMPONENT} +) + # IMPORTANT: required to be included AFTER setting all property overrides include(CPack REQUIRED) diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 46d23f7b91..8fe2fe2c1c 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -286,7 +286,7 @@ endfunction() function(ly_setup_others) # List of directories we want to install relative to engine root - set(DIRECTORIES_TO_INSTALL Tools/LyTestTools Tools/RemoteConsole Tools/Redistributables/CMake) + set(DIRECTORIES_TO_INSTALL Tools/LyTestTools Tools/RemoteConsole) foreach(dir ${DIRECTORIES_TO_INSTALL}) get_filename_component(install_path ${dir} DIRECTORY) diff --git a/cmake/Platform/Windows/Packaging/PostInstallSetup.wxs b/cmake/Platform/Windows/Packaging/PostInstallSetup.wxs index ebcaa9502f..d4f6c181dd 100644 --- a/cmake/Platform/Windows/Packaging/PostInstallSetup.wxs +++ b/cmake/Platform/Windows/Packaging/PostInstallSetup.wxs @@ -43,16 +43,14 @@ - - diff --git a/cmake/Platform/Windows/Packaging_windows.cmake b/cmake/Platform/Windows/Packaging_windows.cmake index b7db250fda..db9c7fc906 100644 --- a/cmake/Platform/Windows/Packaging_windows.cmake +++ b/cmake/Platform/Windows/Packaging_windows.cmake @@ -28,6 +28,10 @@ endif() set(CPACK_GENERATOR "WIX") +set(_cmake_package_name "cmake-${CPACK_DESIRED_CMAKE_VERSION}-windows-x86_64") +set(CPACK_CMAKE_PACKAGE_FILE "${_cmake_package_name}.zip") +set(CPACK_CMAKE_PACKAGE_HASH "15a49e2ab81c1822d75b1b1a92f7863f58e31f6d6aac1c4103eef2b071be3112") + # CPack will generate the WiX product/upgrade GUIDs further down the chain if they weren't supplied # however, they are unique for each run. instead, let's do the auto generation here and add it to # the cache for run persistence and have the ability to detect if they are still being used. @@ -106,4 +110,5 @@ endif() set(CPACK_WIX_CANDLE_EXTRA_FLAGS -dCPACK_EMBED_ARTIFACTS=${_embed_artifacts} + -dCPACK_CMAKE_PACKAGE_NAME=${_cmake_package_name} ) From 7e023c36767b33fe3d78893eaf6120501b611760 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Wed, 26 May 2021 20:23:31 -0700 Subject: [PATCH 14/41] ATOM-15133 "Clean Up EnhancedPBR" Updated material type files for StandardPBR, EnhancedPBR, and Skin to align with each other as much as possible. There were minor cases like some property settings were different, properties in different order, comments, and formatting. There were major cases as well, like EnhancedPBR using clunky built in functors where lua functors would be better, property visibility state wasn't right, properties were missing, etc. I also added a new HasShaderWithTag function for lua functors. This is used in StandardPBR_ShaderEnable.lua to allow this script to be used for both StandardPBR and EnhancedPBR (EnhancedPBR doesn't have the low end pipeline shaders). --- .../Materials/Types/EnhancedPBR.materialtype | 753 ++++-------------- .../Assets/Materials/Types/Skin.materialtype | 41 +- .../Materials/Types/StandardPBR.materialtype | 28 +- .../Types/StandardPBR_ShaderEnable.lua | 30 +- .../RPI.Reflect/Material/LuaMaterialFunctor.h | 1 + .../Material/LuaMaterialFunctor.cpp | 6 + ...SubsurfaceScattering_Transmission.material | 1 - 7 files changed, 240 insertions(+), 620 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index a085afa327..4c988c590a 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -1,5 +1,5 @@ { - "description": "Material Type with properties used to define Enhanced PBR material shading model.", + "description": "Material Type with properties used to define Enhanced PBR, a metallic-roughness Physically-Based Rendering (PBR) material shading model, with advanced features like subsurface scattering, transmission, and anisotropy.", "propertyLayout": { "version": 3, "groups": [ @@ -32,7 +32,7 @@ "id": "clearCoat", "displayName": "Clear Coat", "description": "Properties for configuring gloss clear coat" - }, + }, { "id": "normal", "displayName": "Normal", @@ -205,6 +205,13 @@ "id": "m_baseColorMap" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, { "id": "textureMapUv", "displayName": "UV", @@ -228,13 +235,6 @@ "type": "ShaderOption", "id": "o_baseColorTextureBlendMode" } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map.", - "type": "Bool", - "defaultValue": true } ], "metallic": [ @@ -261,6 +261,13 @@ "id": "m_metallicMap" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, { "id": "textureMapUv", "displayName": "UV", @@ -272,29 +279,9 @@ "type": "ShaderInput", "id": "m_metallicMapUvIndex" } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true } ], "roughness": [ - { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the values", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "id": "m_roughnessFactor" - } - }, { "id": "textureMap", "displayName": "Texture Map", @@ -305,6 +292,13 @@ "id": "m_roughnessMap" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, { "id": "textureMapUv", "displayName": "UV", @@ -346,11 +340,18 @@ } }, { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "id": "factor", + "displayName": "Factor", + "description": "Controls the roughness value", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "id": "m_roughnessFactor" + } } ], "anisotropy": [ @@ -416,6 +417,13 @@ "id": "m_specularF0Map" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, { "id": "textureMapUv", "displayName": "UV", @@ -428,13 +436,7 @@ "id": "m_specularF0MapUvIndex" } }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, + // Consider moving this to the "general" group to be consistent with StandardMultilayerPBR { "id": "enableMultiScatterCompensation", "displayName": "Multiscattering Compensation", @@ -452,11 +454,7 @@ "displayName": "Enable", "description": "Enable clear coat", "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderOption", - "id": "o_clearCoat_feature_enabled" - } + "defaultValue": false }, { "id": "factor", @@ -481,6 +479,13 @@ "id": "m_clearCoatInfluenceMap" } }, + { + "id": "useInfluenceMap", + "displayName": " Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, { "id": "influenceMapUv", "displayName": " UV", @@ -493,13 +498,6 @@ "id": "m_clearCoatInfluenceMapUvIndex" } }, - { - "id": "useInfluenceMap", - "displayName": " Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, { "id": "roughness", "displayName": "Roughness", @@ -523,6 +521,13 @@ "id": "m_clearCoatRoughnessMap" } }, + { + "id": "useRoughnessMap", + "displayName": " Use Texture", + "description": "Whether to use the texture map, or just default to the roughness value.", + "type": "Bool", + "defaultValue": true + }, { "id": "roughnessMapUv", "displayName": " UV", @@ -535,13 +540,6 @@ "id": "m_clearCoatRoughnessMapUvIndex" } }, - { - "id": "useRoughnessMap", - "displayName": " Use Texture", - "description": "Whether to use the texture map, or just default to the roughness value.", - "type": "Bool", - "defaultValue": true - }, { "id": "normalStrength", "displayName": "Normal Strength", @@ -565,9 +563,16 @@ "id": "m_clearCoatNormalMap" } }, + { + "id": "useNormalMap", + "displayName": " Use Texture", + "description": "Whether to use the normal map", + "type": "Bool", + "defaultValue": true + }, { "id": "normalMapUv", - "displayName": "UV", + "displayName": " UV", "description": "Normal texture map UV set", "type": "Enum", "enumIsUv": true, @@ -576,29 +581,9 @@ "type": "ShaderInput", "id": "m_clearCoatNormalMapUvIndex" } - }, - { - "id": "useNormalMap", - "displayName": "Use Texture", - "description": "Whether to use the normal map", - "type": "Bool", - "defaultValue": true } ], "normal": [ - { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the values", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "softMax": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_normalFactor" - } - }, { "id": "textureMap", "displayName": "Texture Map", @@ -609,6 +594,13 @@ "id": "m_normalMap" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just rely on vertex normals.", + "type": "Bool", + "defaultValue": true + }, { "id": "textureMapUv", "displayName": "UV", @@ -621,13 +613,6 @@ "id": "m_normalMapUvIndex" } }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just rely on vertex normals.", - "type": "Bool", - "defaultValue": true - }, { "id": "flipX", "displayName": "Flip X Channel", @@ -649,6 +634,19 @@ "type": "ShaderInput", "id": "m_flipNormalY" } + }, + { + "id": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the values", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_normalFactor" + } } ], "opacity": [ @@ -872,18 +870,14 @@ "displayName": "Enable", "description": "Enable the emissive group", "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderOption", - "id": "o_emissiveEnabled" - } + "defaultValue": false }, { "id": "unit", "displayName": "Units", "description": "The photometric units of the Intensity property.", "type": "Enum", - "enumValues": [ "Ev100" ], + "enumValues": ["Ev100"], "defaultValue": "Ev100" }, { @@ -918,24 +912,24 @@ "id": "m_emissiveMap" } }, - { - "id": "textureMapUv", - "displayName": "UV", - "description": "Emissive texture map UV set", - "type": "Enum", - "enumValues": [ "UV0", "UV1" ], - "defaultValue": "UV0", - "connection": { - "type": "ShaderInput", - "id": "m_emissiveMapUvIndex" - } - }, { "id": "useTexture", "displayName": "Use Texture", "description": "Whether to use the texture map.", "type": "Bool", "defaultValue": true + }, + { + "id": "textureMapUv", + "displayName": "UV", + "description": "Emissive texture map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_emissiveMapUvIndex" + } } ], "parallax": [ @@ -961,8 +955,8 @@ "displayName": "UV", "description": "Depth texture map UV set", "type": "Enum", - "enumValues": [ "UV0", "UV1" ], - "defaultValue": "UV0", + "enumIsUv": true, + "defaultValue": "Tiled", "connection": { "type": "ShaderInput", "id": "m_parallaxUvIndex" @@ -1055,7 +1049,7 @@ "subsurfaceScattering": [ { "id": "enableSubsurfaceScattering", - "displayName": "Enable Subsurface Scattering", + "displayName": "Subsurface Scattering", "description": "Enable subsurface scattering feature, this will disable metallic and parallax mapping property due to incompatibility", "type": "Bool", "defaultValue": false, @@ -1069,7 +1063,7 @@ "displayName": " Factor", "description": "Strength factor for scaling percentage of subsurface scattering effect applied", "type": "float", - "defaultValue": 0.0, + "defaultValue": 1.0, "min": 0.0, "max": 1.0, "connection": { @@ -1087,18 +1081,6 @@ "id": "m_subsurfaceScatteringInfluenceMap" } }, - { - "id": "influenceMapUv", - "displayName": " UV", - "description": "Influence map UV set", - "type": "Enum", - "enumValues": [ "UV0", "UV1" ], - "defaultValue": "UV0", - "connection": { - "type": "ShaderInput", - "id": "m_subsurfaceScatteringInfluenceMapUvIndex" - } - }, { "id": "useInfluenceMap", "displayName": " Use Influence Map", @@ -1106,6 +1088,18 @@ "type": "Bool", "defaultValue": true }, + { + "id": "influenceMapUv", + "displayName": " UV", + "description": "Influence map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_subsurfaceScatteringInfluenceMapUvIndex" + } + }, { "id": "scatterColor", "displayName": " Scatter color", @@ -1136,11 +1130,16 @@ } }, { - "id": "enableTransmission", - "displayName": "Enable Transmission", - "description": "Enable transmission feature", - "type": "Bool", - "defaultValue": false + "id": "transmissionMode", + "displayName": "Transmission", + "description": "Algorithm used for calculating transmission", + "type": "Enum", + "enumValues": [ "None", "ThickObject", "ThinObject" ], + "defaultValue": "None", + "connection": { + "type": "ShaderOption", + "id": "o_transmission_mode" + } }, { "id": "thickness", @@ -1161,18 +1160,6 @@ "id": "m_transmissionThicknessMap" } }, - { - "id": "thicknessMapUv", - "displayName": " UV", - "description": "Thickness map UV set", - "type": "Enum", - "enumValues": [ "UV0", "UV1" ], - "defaultValue": "UV0", - "connection": { - "type": "ShaderInput", - "id": "m_transmissionThicknessMapUvIndex" - } - }, { "id": "useThicknessMap", "displayName": " Use Thickness Map", @@ -1180,6 +1167,18 @@ "type": "Bool", "defaultValue": true }, + { + "id": "thicknessMapUv", + "displayName": " UV", + "description": "Thickness map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_transmissionThicknessMapUvIndex" + } + }, { "id": "transmissionTint", "displayName": " Transmission Tint", @@ -1187,18 +1186,6 @@ "type": "Color", "defaultValue": [ 1.0, 0.8, 0.6 ] }, - { - "id": "transmissionMode", - "displayName": " Mode", - "description": "Algorithm used for calculating transmission", - "type": "Enum", - "enumValues": [ "None", "ThickObject", "ThinObject" ], - "defaultValue": "None", - "connection": { - "type": "ShaderOption", - "id": "o_transmission_mode" - } - }, { "id": "transmissionPower", "displayName": " Power", @@ -1287,7 +1274,7 @@ } }, { - "id": "detailMapsMapUv", + "id": "textureMapUv", "displayName": "Detail Map UVs", "description": "Which UV set to use for detail map texture sampling", "type": "Enum", @@ -1506,7 +1493,7 @@ { "file": "Shaders/Depth/DepthPassTransparentMax.shader", "tag": "DepthPassTransparentMax" - } + } ], "functors": [ { @@ -1549,26 +1536,9 @@ "lightUnitProperty": "emissive.unit", "shaderInput": "m_emissiveIntensity", "ev100Index": 0, - "nitIndex": 1, - "ev100MinMax": [ -10, 20 ], - "nitMinMax": [ 0.001, 100000.0 ] - } - }, - { - // Enable/Disable shader based on different option. - "type": "ShaderEnable", - "args": { - "opacityMode": "opacity.mode", - "parallaxEnable": "parallax.enable", - "parallaxPdoEnable": "parallax.pdo", - "pbrShaderNoEdsIndex": 0, - "pbrShaderWithEdsIndex": 1, - "shadowShaderNoPSIndex": 2, - "shadowShaderWithPSIndex": 3, - "depthShaderNoPSIndex": 4, - "depthShaderWithPSIndex": 5, - "depthShaderTransparentMin": 8, - "depthShaderTransparentMax": 9 + "nitIndex" : 1, + "ev100MinMax": [-10, 20], + "nitMinMax": [0.001, 100000.0] } }, { @@ -1590,120 +1560,40 @@ "tintThickenssShaderInput": "m_transmissionTintThickness" } }, - { - // Reads material properties to determine whether a specific texture map should be sampled at runtime, and sets a shader option accordingly. - // @param textureProperty - which material property contains the texture asset reference (or maybe null) - // @param useTextureProperty - a boolean flag that toggles whether the texture should be sampled (if it's not null) - // @param shaderTags - which shader in the 'shaders' list above is configured by this functor - // @param shaderOption - the name of a shader option in the AZSL file that controls sampling of this texture + { "type": "UseTexture", "args": { "textureProperty": "baseColor.textureMap", - "dependentProperties": ["baseColor.textureMapUv"], "useTextureProperty": "baseColor.useTexture", - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], + "dependentProperties": ["baseColor.textureMapUv", "baseColor.textureBlendMode"], "shaderOption": "o_baseColor_useTexture" } }, { - // See the comment above for details. "type": "UseTexture", "args": { "textureProperty": "metallic.textureMap", - "dependentProperties": ["metallic.textureMapUv"], "useTextureProperty": "metallic.useTexture", - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], + "dependentProperties": ["metallic.textureMapUv"], "shaderOption": "o_metallic_useTexture" } }, { - // See the comment above for details. - "type": "UseTexture", - "args": { - "textureProperty": "roughness.textureMap", - "dependentProperties": ["roughness.textureMapUv"], - "useTextureProperty": "roughness.useTexture", - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_roughness_useTexture" - } - }, - { - // See the comment above for details. "type": "UseTexture", "args": { "textureProperty": "specularF0.textureMap", - "dependentProperties": ["specularF0.textureMapUv"], "useTextureProperty": "specularF0.useTexture", - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], + "dependentProperties": ["specularF0.textureMapUv"], "shaderOption": "o_specularF0_useTexture" } }, { - // See the comment above for details. - "type": "UseTexture", - "args": { - "textureProperty": "clearCoat.influenceMap", - "dependentProperties": ["clearCoat.influenceMapUv"], - "useTextureProperty": "clearCoat.useInfluenceMap", - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_clearCoat_factor_useTexture" - } - }, - { - // See the comment above for details. - "type": "UseTexture", - "args": { - "textureProperty": "clearCoat.roughnessMap", - "dependentProperties": ["clearCoat.roughnessMapUv"], - "useTextureProperty": "clearCoat.useRoughnessMap", - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_clearCoat_roughness_useTexture" - } - }, - { - // See the comment above for details. - "type": "UseTexture", - "args": { - "textureProperty": "clearCoat.normalMap", - "dependentProperties": ["clearCoat.normalMapUv"], - "useTextureProperty": "clearCoat.useNormalMap", - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_clearCoat_normal_useTexture" - } - }, - { - // See the comment above for details. "type": "UseTexture", "args": { "textureProperty": "normal.textureMap", - "dependentProperties": ["normal.textureMapUv"], "useTextureProperty": "normal.useTexture", - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_normal_useTexture" + "dependentProperties": ["normal.textureMapUv", "normal.factor", "normal.flipX", "normal.flipY"], + "shaderOption": "o_normal_useTexture" } }, { @@ -1725,335 +1615,21 @@ } }, { - // See the comment above for details. - "type": "UseTexture", + "type": "Lua", "args": { - "textureProperty": "emissive.textureMap", - "dependentProperties": ["emissive.textureMapUv"], - "useTextureProperty": "emissive.useTexture", - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_emissive_useTexture" + "file": "StandardPBR_ClearCoatState.lua" } }, { - // See the comment above for details. - "type": "UseTexture", + "type": "Lua", "args": { - "textureProperty": "subsurfaceScattering.influenceMap", - "dependentProperties": ["subsurfaceScattering.influenceMapUv"], - "useTextureProperty": "subsurfaceScattering.useInfluenceMap", - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_subsurfaceScattering_useTexture" + "file": "StandardPBR_ClearCoatEnableFeature.lua" } }, { - // See the comment above for details. - "type": "UseTexture", + "type": "Lua", "args": { - "textureProperty": "subsurfaceScattering.thicknessMap", - "dependentProperties": ["subsurfaceScattering.thicknessMapUv"], - "useTextureProperty": "subsurfaceScattering.useThicknessMap", - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_transmission_useTexture" - } - }, - { - // Controls visibility for properties in the editor. - // @param actions - a list of actions that are executed in order. visibility will be set when triggerProperty hits the triggerValue. - // @param affectedProperties - the properties that are affected by actions. - "type": "UpdatePropertyVisibility", - "args": { - "actions": [ - { - "triggerProperty": "emissive.enable", - "triggerValue": true, - "visibility": "Enabled" - }, - { - "triggerProperty": "emissive.enable", - "triggerValue": false, - "visibility": "Hidden" - } - ], - "affectedProperties": [ - "emissive.color", - "emissive.intensity", - "emissive.useTexture", - "emissive.unit" - ] - } - }, - { - // Controls visibility for properties in the editor. - // @param actions - a list of actions that are executed in order. visibility will be set when triggerProperty hits the triggerValue. - // @param affectedProperties - the properties that are affected by actions. - "type": "UpdatePropertyVisibility", - "args": { - "actions": [ - { - "triggerProperty": "emissive.useTexture", - "triggerValue": true, - "visibility": "Enabled" - }, - { - "triggerProperty": "emissive.useTexture", - "triggerValue": false, - "visibility": "Disabled" - }, - { - "triggerProperty": "emissive.enable", - "triggerValue": false, - "visibility": "Hidden" - } - ], - "affectedProperties": [ - "emissive.textureMap", - "emissive.textureMapUv" - ] - } - }, - { - "type": "UpdatePropertyVisibility", - "args": { - "actions": [ - { - "triggerProperty": "clearCoat.useInfluenceMap", - "triggerValue": true, - "visibility": "Enabled" - }, - { - "triggerProperty": "clearCoat.useInfluenceMap", - "triggerValue": false, - "visibility": "Disabled" - }, - { - "triggerProperty": "clearCoat.enable", - "triggerValue": false, - "visibility": "Hidden" - } - ], - "affectedProperties": [ - "clearCoat.influenceMap", - "clearCoat.influenceMapUv" - ] - } - }, - { - "type": "UpdatePropertyVisibility", - "args": { - "actions": [ - { - "triggerProperty": "clearCoat.useRoughnessMap", - "triggerValue": true, - "visibility": "Enabled" - }, - { - "triggerProperty": "clearCoat.useRoughnessMap", - "triggerValue": false, - "visibility": "Disabled" - }, - { - "triggerProperty": "clearCoat.enable", - "triggerValue": false, - "visibility": "Hidden" - } - ], - "affectedProperties": [ - "clearCoat.roughnessMap", - "clearCoat.roughnessMapUv" - ] - } - }, - { - "type": "UpdatePropertyVisibility", - "args": { - "actions": [ - { - "triggerProperty": "clearCoat.useNormalMap", - "triggerValue": true, - "visibility": "Enabled" - }, - { - "triggerProperty": "clearCoat.useNormalMap", - "triggerValue": false, - "visibility": "Disabled" - }, - { - "triggerProperty": "clearCoat.enable", - "triggerValue": false, - "visibility": "Hidden" - } - ], - "affectedProperties": [ - "clearCoat.normalMap", - "clearCoat.normalMapUv" - ] - } - - }, - { - "type": "UpdatePropertyVisibility", - "args": { - "actions": [ - { - "triggerProperty": "subsurfaceScattering.useInfluenceMap", - "triggerValue": true, - "visibility": "Enabled" - }, - { - "triggerProperty": "subsurfaceScattering.useInfluenceMap", - "triggerValue": false, - "visibility": "Disabled" - }, - { - "triggerProperty": "subsurfaceScattering.enableSubsurfaceScattering", - "triggerValue": false, - "visibility": "Hidden" - } - ], - "affectedProperties": [ - "subsurfaceScattering.influenceMap", - "subsurfaceScattering.influenceMapUv" - ] - } - }, - { - "type": "UpdatePropertyVisibility", - "args": { - "actions": [ - { - "triggerProperty": "subsurfaceScattering.useThicknessMap", - "triggerValue": true, - "visibility": "Enabled" - }, - { - "triggerProperty": "subsurfaceScattering.useThicknessMap", - "triggerValue": false, - "visibility": "Disabled" - }, - { - "triggerProperty": "subsurfaceScattering.enableTransmission", - "triggerValue": false, - "visibility": "Hidden" - } - ], - "affectedProperties": [ - "subsurfaceScattering.thicknessMap", - "subsurfaceScattering.thicknessMapUv" - ] - } - }, - { - "type": "UpdatePropertyVisibility", - "args": { - "actions": [ - { - "triggerProperty": "clearCoat.enable", - "triggerValue": true, - "visibility": "Enabled" - }, - { - "triggerProperty": "clearCoat.enable", - "triggerValue": false, - "visibility": "Hidden" - } - ], - "affectedProperties": [ - "clearCoat.factor", - "clearCoat.useInfluenceMap", - "clearCoat.roughness", - "clearCoat.useRoughnessMap", - "clearCoat.useNormalMap" - ] - } - }, - { - "type": "UpdatePropertyVisibility", - "args": { - "actions": [ - { - "triggerProperty": "subsurfaceScattering.transmissionMode", - "triggerValue": "ThickObject", - "visibility": "Enabled" - }, - { - "triggerProperty": "subsurfaceScattering.transmissionMode", - "triggerValue": "None", - "visibility": "Hidden" - }, - { - "triggerProperty": "subsurfaceScattering.transmissionMode", - "triggerValue": "ThinObject", - "visibility": "Hidden" - }, - { - "triggerProperty": "subsurfaceScattering.enableTransmission", - "triggerValue": false, - "visibility": "Hidden" - } - ], - "affectedProperties": [ - "subsurfaceScattering.transmissionPower", - "subsurfaceScattering.transmissionDistortion", - "subsurfaceScattering.transmissionAttenuation" - ] - } - }, - { - "type": "UpdatePropertyVisibility", - "args": { - "actions": [ - { - "triggerProperty": "subsurfaceScattering.enableSubsurfaceScattering", - "triggerValue": true, - "visibility": "Enabled" - }, - { - "triggerProperty": "subsurfaceScattering.enableSubsurfaceScattering", - "triggerValue": false, - "visibility": "Hidden" - } - ], - "affectedProperties": [ - "subsurfaceScattering.subsurfaceScatterFactor", - "subsurfaceScattering.useInfluenceMap", - "subsurfaceScattering.scatterColor", - "subsurfaceScattering.scatterDistance", - "subsurfaceScattering.quality" - ] - } - }, - { - "type": "UpdatePropertyVisibility", - "args": { - "actions": [ - { - "triggerProperty": "subsurfaceScattering.enableTransmission", - "triggerValue": true, - "visibility": "Enabled" - }, - { - "triggerProperty": "subsurfaceScattering.enableTransmission", - "triggerValue": false, - "visibility": "Hidden" - } - ], - "affectedProperties": [ - "subsurfaceScattering.thickness", - "subsurfaceScattering.useThicknessMap", - "subsurfaceScattering.transmissionTint", - "subsurfaceScattering.transmissionMode", - "subsurfaceScattering.transmissionScale" - ] + "file": "StandardPBR_EmissiveState.lua" } }, { @@ -2062,6 +1638,18 @@ "file": "StandardPBR_ParallaxState.lua" } }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_Roughness.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_SubsurfaceState.lua" + } + }, { "type": "Lua", "args": { @@ -2097,6 +1685,12 @@ "args": { "file": "MaterialInputs/DetailMapsCommonFunctor.lua" } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_ShaderEnable.lua" + } } ], "uvNameMap": { @@ -2104,3 +1698,4 @@ "UV1": "Unwrapped" } } + diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index 044b267645..f8c49d579c 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -287,6 +287,13 @@ "id": "m_specularF0Map" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, { "id": "textureMapUv", "displayName": "UV", @@ -299,13 +306,7 @@ "id": "m_specularF0MapUvIndex" } }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture map, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, + // Consider moving this to the "general" group to be consistent with StandardMultilayerPBR { "id": "enableMultiScatterCompensation", "displayName": "Multiscattering Compensation", @@ -616,7 +617,7 @@ "type": "float", "defaultValue": 6.0, "min": 0.0, - "softMax": 20.0 + "softMax": 20.0 }, { "id": "transmissionDistortion", @@ -1011,18 +1012,18 @@ "type": "HandleSubsurfaceScatteringParameters", "args": { "mode": "subsurfaceScattering.transmissionMode", - "scale" : "subsurfaceScattering.transmissionScale", - "power" : "subsurfaceScattering.transmissionPower", - "distortion" : "subsurfaceScattering.transmissionDistortion", - "attenuation" : "subsurfaceScattering.transmissionAttenuation", - "tintColor" : "subsurfaceScattering.transmissionTint", - "thickness" : "subsurfaceScattering.thickness", + "scale": "subsurfaceScattering.transmissionScale", + "power": "subsurfaceScattering.transmissionPower", + "distortion": "subsurfaceScattering.transmissionDistortion", + "attenuation": "subsurfaceScattering.transmissionAttenuation", + "tintColor": "subsurfaceScattering.transmissionTint", + "thickness": "subsurfaceScattering.thickness", "enabled": "subsurfaceScattering.enableSubsurfaceScattering", - "scatterDistanceColor" : "subsurfaceScattering.scatterColor", - "scatterDistanceIntensity" : "subsurfaceScattering.scatterDistance", - "scatterDistanceShaderInput" : "m_scatterDistance", - "parametersShaderInput" : "m_transmissionParams", - "tintThickenssShaderInput" : "m_transmissionTintThickness" + "scatterDistanceColor": "subsurfaceScattering.scatterColor", + "scatterDistanceIntensity": "subsurfaceScattering.scatterDistance", + "scatterDistanceShaderInput": "m_scatterDistance", + "parametersShaderInput": "m_transmissionParams", + "tintThickenssShaderInput": "m_transmissionTintThickness" } }, { @@ -1038,8 +1039,8 @@ "type": "UseTexture", "args": { "textureProperty": "specularF0.textureMap", - "dependentProperties": ["specularF0.textureMapUv"], "useTextureProperty": "specularF0.useTexture", + "dependentProperties": ["specularF0.textureMapUv"], "shaderOption": "o_specularF0_useTexture" } }, diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype index 04e6c0f501..038e65a89f 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype @@ -674,7 +674,7 @@ { "id": "tileU", "displayName": "Tile U", - "description": "Scales texture coordinates in V.", + "description": "Scales texture coordinates in U.", "type": "float", "defaultValue": 1.0, "step": 0.1 @@ -1139,7 +1139,7 @@ "type": "float", "defaultValue": 6.0, "min": 0.0, - "softMax": 20.0 + "softMax": 20.0 }, { "id": "transmissionDistortion", @@ -1170,7 +1170,7 @@ } ], "irradiance": [ - // Note: this property group is used in the DiffuseGlobalIllumination pass, it is not read by the StandardPBR shader + // Note: this property group is used in the DiffuseGlobalIllumination pass and not by the main forward shader { "id": "color", "displayName": "Color", @@ -1277,18 +1277,18 @@ "type": "HandleSubsurfaceScatteringParameters", "args": { "mode": "subsurfaceScattering.transmissionMode", - "scale" : "subsurfaceScattering.transmissionScale", - "power" : "subsurfaceScattering.transmissionPower", - "distortion" : "subsurfaceScattering.transmissionDistortion", - "attenuation" : "subsurfaceScattering.transmissionAttenuation", - "tintColor" : "subsurfaceScattering.transmissionTint", - "thickness" : "subsurfaceScattering.thickness", + "scale": "subsurfaceScattering.transmissionScale", + "power": "subsurfaceScattering.transmissionPower", + "distortion": "subsurfaceScattering.transmissionDistortion", + "attenuation": "subsurfaceScattering.transmissionAttenuation", + "tintColor": "subsurfaceScattering.transmissionTint", + "thickness": "subsurfaceScattering.thickness", "enabled": "subsurfaceScattering.enableSubsurfaceScattering", - "scatterDistanceColor" : "subsurfaceScattering.scatterColor", - "scatterDistanceIntensity" : "subsurfaceScattering.scatterDistance", - "scatterDistanceShaderInput" : "m_scatterDistance", - "parametersShaderInput" : "m_transmissionParams", - "tintThickenssShaderInput" : "m_transmissionTintThickness" + "scatterDistanceColor": "subsurfaceScattering.scatterColor", + "scatterDistanceIntensity": "subsurfaceScattering.scatterDistance", + "scatterDistanceShaderInput": "m_scatterDistance", + "parametersShaderInput": "m_transmissionParams", + "tintThickenssShaderInput": "m_transmissionTintThickness" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua index e502eb38f8..26c163d61b 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua @@ -21,6 +21,20 @@ OpacityMode_Cutout = 1 OpacityMode_Blended = 2 OpacityMode_TintedTransparent = 3 +function TryGetShaderByTag(context, shaderTag) + if context:HasShaderWithTag(shaderTag) then + return context:GetShaderByTag(shaderTag) + else + return nil + end +end + +function TrySetShaderEnabled(shader, enabled) + if shader then + shader:SetEnabled(enabled) + end +end + function Process(context) local opacityMode = context:GetMaterialPropertyValue_enum("opacity.mode") local parallaxEnabled = context:GetMaterialPropertyValue_bool("parallax.enable") @@ -29,33 +43,37 @@ function Process(context) local depthPass = context:GetShaderByTag("DepthPass") local shadowMap = context:GetShaderByTag("Shadowmap") local forwardPassEDS = context:GetShaderByTag("ForwardPass_EDS") - local lowEndForwardEDS = context:GetShaderByTag("LowEndForward_EDS") local depthPassWithPS = context:GetShaderByTag("DepthPass_WithPS") local shadowMapWithPS = context:GetShaderByTag("Shadowmap_WithPS") local forwardPass = context:GetShaderByTag("ForwardPass") - local lowEndForward = context:GetShaderByTag("LowEndForward") + + -- Use TryGetShaderByTag because these shaders only exist in StandardPBR but this script is also used for EnhancedPBR + local lowEndForwardEDS = TryGetShaderByTag(context, "LowEndForward_EDS") + local lowEndForward = TryGetShaderByTag(context, "LowEndForward") if parallaxEnabled and parallaxPdoEnabled then depthPass:SetEnabled(false) shadowMap:SetEnabled(false) forwardPassEDS:SetEnabled(false) - lowEndForwardEDS:SetEnabled(false) depthPassWithPS:SetEnabled(true) shadowMapWithPS:SetEnabled(true) forwardPass:SetEnabled(true) - lowEndForward:SetEnabled(true) + + TrySetShaderEnabled(lowEndForwardEDS, false) + TrySetShaderEnabled(lowEndForward, true) else depthPass:SetEnabled(opacityMode == OpacityMode_Opaque) shadowMap:SetEnabled(opacityMode == OpacityMode_Opaque) forwardPassEDS:SetEnabled((opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent)) - lowEndForwardEDS:SetEnabled((opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent)) depthPassWithPS:SetEnabled(opacityMode == OpacityMode_Cutout) shadowMapWithPS:SetEnabled(opacityMode == OpacityMode_Cutout) forwardPass:SetEnabled(opacityMode == OpacityMode_Cutout) - lowEndForward:SetEnabled(opacityMode == OpacityMode_Cutout) + + TrySetShaderEnabled(lowEndForwardEDS, (opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent)) + TrySetShaderEnabled(lowEndForward, opacityMode == OpacityMode_Cutout) end context:GetShaderByTag("DepthPassTransparentMin"):SetEnabled((opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent)) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h index 396ba14810..f372f40981 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h @@ -288,6 +288,7 @@ namespace AZ AZStd::size_t GetShaderCount() const; LuaMaterialFunctorShaderItem GetShader(AZStd::size_t index); LuaMaterialFunctorShaderItem GetShaderByTag(const char* shaderTag); + bool HasShaderWithTag(const char* shaderTag); private: diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp index 7db5f12560..d6421e1337 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp @@ -296,6 +296,7 @@ namespace AZ ->Method("GetShaderCount", &LuaMaterialFunctorRuntimeContext::GetShaderCount) ->Method("GetShader", &LuaMaterialFunctorRuntimeContext::GetShader) ->Method("GetShaderByTag", &LuaMaterialFunctorRuntimeContext::GetShaderByTag) + ->Method("HasShaderWithTag", &LuaMaterialFunctorRuntimeContext::HasShaderWithTag) ; } @@ -424,6 +425,11 @@ namespace AZ return LuaMaterialFunctorShaderItem{nullptr}; } } + + bool LuaMaterialFunctorRuntimeContext::HasShaderWithTag(const char* shaderTag) + { + return m_runtimeContextImpl->m_shaderCollection->HasShaderTag(AZ::Name{shaderTag}); + } void LuaMaterialFunctorEditorContext::LuaMaterialFunctorEditorContext::Reflect(BehaviorContext* behaviorContext) { diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission.material index dbaf6cb587..38adbc70cd 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission.material @@ -6,7 +6,6 @@ "properties": { "subsurfaceScattering": { "enableSubsurfaceScattering": true, - "enableTransmission": true, "scatterDistance": 64.6464614868164, "subsurfaceScatterFactor": 1.0, "thicknessMap": "TestData/Textures/checker8x8_512.png", From c84989832d82719e1687386676b0fb0944faf539 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Wed, 26 May 2021 21:07:49 -0700 Subject: [PATCH 15/41] ATOM-13216 Delete Deprecated Functors Removed unused PropertyVisibilityFunctor and ShaderEnableFunctor --- .../Code/Source/CommonSystemComponent.cpp | 4 - .../Source/EditorCommonSystemComponent.cpp | 6 - .../Material/PropertyVisibilityFunctor.cpp | 77 ------------ .../Material/PropertyVisibilityFunctor.h | 49 -------- .../PropertyVisibilityFunctorSourceData.cpp | 100 --------------- .../PropertyVisibilityFunctorSourceData.h | 48 -------- .../Source/Material/ShaderEnableFunctor.cpp | 74 ----------- .../Source/Material/ShaderEnableFunctor.h | 63 ---------- .../ShaderEnableFunctorSourceData.cpp | 116 ------------------ .../Material/ShaderEnableFunctorSourceData.h | 52 -------- .../atom_feature_common_editor_files.cmake | 4 - .../Code/atom_feature_common_files.cmake | 4 - 12 files changed, 597 deletions(-) delete mode 100644 Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.cpp delete mode 100644 Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.h delete mode 100644 Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.cpp delete mode 100644 Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.h delete mode 100644 Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.cpp delete mode 100644 Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.h delete mode 100644 Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.cpp delete mode 100644 Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.h diff --git a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp index 089a6168b1..16f20d7178 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp @@ -14,8 +14,6 @@ #include #include #include -#include -#include #include #include @@ -114,7 +112,6 @@ namespace AZ ProjectedShadowFeatureProcessor::Reflect(context); SkyBoxFeatureProcessor::Reflect(context); UseTextureFunctor::Reflect(context); - PropertyVisibilityFunctor::Reflect(context); DrawListFunctor::Reflect(context); SubsurfaceTransmissionParameterFunctor::Reflect(context); Transform2DFunctor::Reflect(context); @@ -126,7 +123,6 @@ namespace AZ DisplayMapperPassData::Reflect(context); ConvertEmissiveUnitFunctor::Reflect(context); LookupTableAsset::Reflect(context); - ShaderEnableFunctor::Reflect(context); ReflectionProbeFeatureProcessor::Reflect(context); DecalTextureArrayFeatureProcessor::Reflect(context); SMAAFeatureProcessor::Reflect(context); diff --git a/Gems/Atom/Feature/Common/Code/Source/EditorCommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/EditorCommonSystemComponent.cpp index 32a29cf4d3..2373d0cb00 100644 --- a/Gems/Atom/Feature/Common/Code/Source/EditorCommonSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/EditorCommonSystemComponent.cpp @@ -12,11 +12,9 @@ #include #include -#include #include #include #include -#include #include #include @@ -58,11 +56,9 @@ namespace AZ } AZ::Render::UseTextureFunctorSourceData::Reflect(context); - AZ::Render::PropertyVisibilityFunctorSourceData::Reflect(context); AZ::Render::DrawListFunctorSourceData::Reflect(context); AZ::Render::Transform2DFunctorSourceData::Reflect(context); AZ::Render::ConvertEmissiveUnitFunctorSourceData::Reflect(context); - AZ::Render::ShaderEnableFunctorSourceData::Reflect(context); AZ::Render::SubsurfaceTransmissionParameterFunctorSourceData::Reflect(context); AZ::Render::EditorLightingPreset::Reflect(context); @@ -104,11 +100,9 @@ namespace AZ } materialFunctorRegistration->RegisterMaterialFunctor("UseTexture", azrtti_typeid()); - materialFunctorRegistration->RegisterMaterialFunctor("UpdatePropertyVisibility", azrtti_typeid()); materialFunctorRegistration->RegisterMaterialFunctor("OverrideDrawList", azrtti_typeid()); materialFunctorRegistration->RegisterMaterialFunctor("Transform2D", azrtti_typeid()); materialFunctorRegistration->RegisterMaterialFunctor("ConvertEmissiveUnit", azrtti_typeid()); - materialFunctorRegistration->RegisterMaterialFunctor("ShaderEnable", azrtti_typeid()); materialFunctorRegistration->RegisterMaterialFunctor("HandleSubsurfaceScatteringParameters", azrtti_typeid()); materialFunctorRegistration->RegisterMaterialFunctor("Lua", azrtti_typeid()); diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.cpp deleted file mode 100644 index da8730f1ed..0000000000 --- a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "PropertyVisibilityFunctor.h" - -namespace AZ -{ - namespace Render - { - void PropertyVisibilityFunctor::Reflect(ReflectContext* context) - { - if (auto* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("triggerProperty", &Action::m_triggerPropertyIndex) - ->Field("triggerValue", &Action::m_triggerValue) - ->Field("visibility", &Action::m_visibility) - ; - serializeContext->Class() - ->Version(1) - ->Field("actions", &PropertyVisibilityFunctor::m_actions) - ->Field("affectedProperties", &PropertyVisibilityFunctor::m_affectedProperties) - ; - } - } - - void PropertyVisibilityFunctor::Process(EditorContext& context) - { - bool visibilityApplied = false; - RPI::MaterialPropertyVisibility lastAppliedVisibility; - - for (const auto& action : m_actions) - { - bool willSetVisibility = false; - if (action.m_triggerValue.Is() || action.m_triggerValue.Is() || action.m_triggerValue.Is()) - { - willSetVisibility = action.m_triggerValue == context.GetMaterialPropertyValue(action.m_triggerPropertyIndex); - } - else if (action.m_triggerValue.Is()) - { - willSetVisibility = AZ::IsClose(action.m_triggerValue.GetValue(), - context.GetMaterialPropertyValue(action.m_triggerPropertyIndex), - std::numeric_limits::epsilon()); - } - else // for types Vector2, Vector3, Vector4, Color, Image - { - AZ_Error("PropertyVisibilityFunctor", false, "Unsupported property data type as an enable property."); - } - - if (willSetVisibility) - { - visibilityApplied = true; - lastAppliedVisibility = action.m_visibility; - } - } - - if (visibilityApplied) - { - for (const auto& propertyIndex : m_affectedProperties) - { - context.SetMaterialPropertyVisibility(propertyIndex, lastAppliedVisibility); - } - } - } - - } // namespace Render -} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.h b/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.h deleted file mode 100644 index d1a7772fc8..0000000000 --- a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include - -namespace AZ -{ - namespace Render - { - //! Materials can use this functor to control when and how to set the visibility of a group of properties. - class PropertyVisibilityFunctor final - : public RPI::MaterialFunctor - { - friend class PropertyVisibilityFunctorSourceData; - public: - AZ_RTTI(AZ::Render::PropertyVisibilityFunctor, "{2582B36F-FA7C-450F-B46A-39AAE18356A0}", RPI::MaterialFunctor); - - static void Reflect(ReflectContext* context); - - void Process(EditorContext& context) override; - - private: - struct Action - { - AZ_TYPE_INFO(AZ::Render::PropertyVisibilityFunctor::Action, "{5DF4D981-9D0C-4040-A6C5-52E1D0BD876B}"); - - RPI::MaterialPropertyIndex m_triggerPropertyIndex; //! The control property for affected properties. - RPI::MaterialPropertyValue m_triggerValue; //! The trigger value of the control property. - RPI::MaterialPropertyVisibility m_visibility; //! The visibility of affected properties when the trigger value is hit. - }; - // Material property inputs... - AZStd::vector m_actions; //! The actions that describes when and what to do with visibilities. - AZStd::vector m_affectedProperties; //! The properties that are affected by actions. - }; - - } // namespace Render -} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.cpp deleted file mode 100644 index 3baf27de60..0000000000 --- a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "PropertyVisibilityFunctorSourceData.h" -#include -#include - -#include - -namespace AZ -{ - namespace Render - { - void PropertyVisibilityFunctorSourceData::Reflect(ReflectContext* context) - { - if (auto* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("triggerProperty", &ActionSourceData::m_triggerPropertyName) - ->Field("triggerValue", &ActionSourceData::m_triggerValue) - ->Field("visibility", &ActionSourceData::m_visibility) - ; - serializeContext->Class() - ->Version(2) - ->Field("actions", &PropertyVisibilityFunctorSourceData::m_actions) - ->Field("affectedProperties", &PropertyVisibilityFunctorSourceData::m_affectedPropertyNames) - ; - } - } - - RPI::MaterialFunctorSourceData::FunctorResult PropertyVisibilityFunctorSourceData::CreateFunctor(const EditorContext& context) const - { - using namespace RPI; - - RPI::Ptr functor = aznew PropertyVisibilityFunctor; - - functor->m_actions.reserve(m_actions.size()); - - for (const auto& actionSource : m_actions) - { - functor->m_actions.emplace_back(); - PropertyVisibilityFunctor::Action& action = functor->m_actions.back(); - action.m_triggerPropertyIndex = context.FindMaterialPropertyIndex(AZ::Name{ actionSource.m_triggerPropertyName }); - if (action.m_triggerPropertyIndex.IsNull()) - { - return Failure(); - } - AddMaterialPropertyDependency(functor, action.m_triggerPropertyIndex); - - if (!actionSource.m_triggerValue.Resolve(*context.GetMaterialPropertiesLayout(), Name{ actionSource.m_triggerPropertyName })) - { - // Error is reported in Resolve(). - return Failure(); - } - - const MaterialPropertyDescriptor* propertyDescriptor = context.GetMaterialPropertiesLayout()->GetPropertyDescriptor(action.m_triggerPropertyIndex); - // Enum type should resolve further to a unit32_t from the string source. - if (propertyDescriptor->GetDataType() == RPI::MaterialPropertyDataType::Enum) - { - if (!RPI::MaterialUtils::ResolveMaterialPropertyEnumValue( - propertyDescriptor, - Name(actionSource.m_triggerValue.GetValue().GetValue()), - action.m_triggerValue)) - { - return Failure(); - } - } - else - { - action.m_triggerValue = actionSource.m_triggerValue.GetValue(); - } - - action.m_visibility = actionSource.m_visibility; - } - - functor->m_affectedProperties.reserve(m_affectedPropertyNames.size()); - for (const AZStd::string& name : m_affectedPropertyNames) - { - RPI::MaterialPropertyIndex index = context.FindMaterialPropertyIndex(AZ::Name{ name }); - if (index.IsNull()) - { - return Failure(); - } - functor->m_affectedProperties.push_back(index); - } - - return Success(RPI::Ptr(functor)); - } - } // namespace Render -} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.h b/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.h deleted file mode 100644 index 6b212f78a0..0000000000 --- a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include "PropertyVisibilityFunctor.h" -#include -#include - -namespace AZ -{ - namespace Render - { - //! Builds a PropertyVisibilityFunctor. - //! Materials can use this functor to control whether a specific property group will be enabled. - class PropertyVisibilityFunctorSourceData final - : public RPI::MaterialFunctorSourceData - { - public: - AZ_RTTI(AZ::Render::PropertyVisibilityFunctorSourceData, "{B44E6929-8FFF-405F-9056-B9B811F97676}", RPI::MaterialFunctorSourceData); - - static void Reflect(ReflectContext* context); - - FunctorResult CreateFunctor(const EditorContext& context) const override; - private: - struct ActionSourceData - { - AZ_TYPE_INFO(AZ::Render::PropertyVisibilityFunctorSourceData::ActionSourceData, "{70E01DA6-0B42-4CCB-AAD0-51980DB43F62}"); - AZStd::string m_triggerPropertyName; //! The control property for affected properties. - RPI::MaterialPropertyValueSourceData m_triggerValue; //! The trigger value of the control property. - RPI::MaterialPropertyVisibility m_visibility; //! The visibility of affected properties when the trigger value is hit. - }; - // Material property inputs... - AZStd::vector m_actions; //! The actions that describes when and what to do with visibilities. - AZStd::vector m_affectedPropertyNames; //! The properties that are affected by actions. - }; - - } // namespace Render -} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.cpp deleted file mode 100644 index dd602cc4ba..0000000000 --- a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "./ShaderEnableFunctor.h" -#include -#include -#include - -namespace AZ -{ - namespace Render - { - void ShaderEnableFunctor::Reflect(ReflectContext* context) - { - if (auto* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(4) - ->Field("opacityModeIndex", &ShaderEnableFunctor::m_opacityModeIndex) - ->Field("parallaxEnableIndex", &ShaderEnableFunctor::m_parallaxEnableIndex) - ->Field("parallaxPdoEnableIndex", &ShaderEnableFunctor::m_parallaxPdoEnableIndex) - ->Field("shadowShaderNoPSIndex", &ShaderEnableFunctor::m_shadowShaderNoPSIndex) - ->Field("shadowShaderWithPSIndex", &ShaderEnableFunctor::m_shadowShaderWithPSIndex) - ->Field("depthShaderNoPSIndex", &ShaderEnableFunctor::m_depthShaderNoPSIndex) - ->Field("depthShaderWithPSIndex", &ShaderEnableFunctor::m_depthShaderWithPSIndex) - ->Field("pbrShaderNoEdsIndex", &ShaderEnableFunctor::m_pbrShaderNoEdsIndex) - ->Field("pbrShaderWithEdsIndex", &ShaderEnableFunctor::m_pbrShaderWithEdsIndex) - ->Field("depthShaderTransparentMin", &ShaderEnableFunctor::m_depthShaderTransparentMin) - ->Field("depthShaderTransparentMax", &ShaderEnableFunctor::m_depthShaderTransparentMax) - ; - } - } - - void ShaderEnableFunctor::Process(RuntimeContext& context) - { - unsigned int opacityMode = context.GetMaterialPropertyValue(m_opacityModeIndex); - bool parallaxEnabled = context.GetMaterialPropertyValue(m_parallaxEnableIndex); - bool parallaxPdoEnabled = context.GetMaterialPropertyValue(m_parallaxPdoEnableIndex); - - if (parallaxEnabled && parallaxPdoEnabled) - { - context.SetShaderEnabled(m_depthShaderNoPSIndex, false); - context.SetShaderEnabled(m_shadowShaderNoPSIndex, false); - context.SetShaderEnabled(m_pbrShaderWithEdsIndex, false); - - context.SetShaderEnabled(m_depthShaderWithPSIndex, true); - context.SetShaderEnabled(m_shadowShaderWithPSIndex, true); - context.SetShaderEnabled(m_pbrShaderNoEdsIndex, true); - } - else - { - context.SetShaderEnabled(m_depthShaderNoPSIndex, opacityMode == OpacityMode::Opaque ); - context.SetShaderEnabled(m_shadowShaderNoPSIndex, opacityMode == OpacityMode::Opaque); - context.SetShaderEnabled(m_pbrShaderWithEdsIndex, opacityMode == OpacityMode::Opaque || opacityMode == OpacityMode::Blended || opacityMode == OpacityMode::TintedTransparent); - - context.SetShaderEnabled(m_depthShaderWithPSIndex, opacityMode == OpacityMode::Cutout); - context.SetShaderEnabled(m_shadowShaderWithPSIndex, opacityMode == OpacityMode::Cutout); - context.SetShaderEnabled(m_pbrShaderNoEdsIndex, opacityMode == OpacityMode::Cutout); - } - - context.SetShaderEnabled(m_depthShaderTransparentMin, opacityMode == OpacityMode::Blended || opacityMode == OpacityMode::TintedTransparent); - context.SetShaderEnabled(m_depthShaderTransparentMax, opacityMode == OpacityMode::Blended || opacityMode == OpacityMode::TintedTransparent); - } - } -} diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.h b/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.h deleted file mode 100644 index ac5f31ba30..0000000000 --- a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include -#include - -namespace AZ -{ - namespace Render - { - enum OpacityMode - { - Opaque = 0, - Cutout, - Blended, - TintedTransparent, - }; - - //! Select shadow and depth shader based on opacity mode and parallax state - //! Opaque: Enable shader without PS - //! Cutout or Parallax enable: Enable shader with PS - //! Blended: Disable both - //! TintedTransparent: Disable both - class ShaderEnableFunctor final - : public RPI::MaterialFunctor - { - friend class ShaderEnableFunctorSourceData; - public: - AZ_RTTI(ShaderEnableFunctor, "{2079A693-FE4F-46A7-95C0-09D88AC156D0}", RPI::MaterialFunctor); - - static void Reflect(ReflectContext* context); - - void Process(RuntimeContext& context) override; - - private: - RPI::MaterialPropertyIndex m_opacityModeIndex; - RPI::MaterialPropertyIndex m_parallaxEnableIndex; - RPI::MaterialPropertyIndex m_parallaxPdoEnableIndex; - - uint32_t m_shadowShaderNoPSIndex = -1; - uint32_t m_shadowShaderWithPSIndex = -1; - uint32_t m_depthShaderNoPSIndex = -1; - uint32_t m_depthShaderWithPSIndex = -1; - uint32_t m_pbrShaderWithEdsIndex = -1; - uint32_t m_pbrShaderNoEdsIndex = -1; - // The following are used by the light culling system to produce min/max depth bounds - uint32_t m_depthShaderTransparentMin = -1; - uint32_t m_depthShaderTransparentMax = -1; - }; - } -} diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.cpp deleted file mode 100644 index 3c16666f82..0000000000 --- a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "./ShaderEnableFunctorSourceData.h" -#include -#include - -namespace AZ -{ - namespace Render - { - void ShaderEnableFunctorSourceData::Reflect(ReflectContext* context) - { - if (auto* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(5) - ->Field("opacityMode", &ShaderEnableFunctorSourceData::m_opacityMode) - ->Field("parallaxEnable", &ShaderEnableFunctorSourceData::m_parallaxEnable) - ->Field("parallaxPdoEnable", &ShaderEnableFunctorSourceData::m_parallaxPdoEnable) - ->Field("shadowShaderNoPSIndex", &ShaderEnableFunctorSourceData::m_shadowShaderNoPSIndex) - ->Field("shadowShaderWithPSIndex", &ShaderEnableFunctorSourceData::m_shadowShaderWithPSIndex) - ->Field("depthShaderNoPSIndex", &ShaderEnableFunctorSourceData::m_depthShaderNoPSIndex) - ->Field("depthShaderWithPSIndex", &ShaderEnableFunctorSourceData::m_depthShaderWithPSIndex) - ->Field("pbrShaderNoEdsIndex", &ShaderEnableFunctorSourceData::m_pbrShaderNoEdsIndex) - ->Field("pbrShaderWithEdsIndex", &ShaderEnableFunctorSourceData::m_pbrShaderWithEdsIndex) - ->Field("depthShaderTransparentMin", &ShaderEnableFunctorSourceData::m_depthShaderTransparentMin) - ->Field("depthShaderTransparentMax", &ShaderEnableFunctorSourceData::m_depthShaderTransparentMax) - ; - } - } - - RPI::MaterialFunctorSourceData::FunctorResult ShaderEnableFunctorSourceData::CreateFunctor(const RuntimeContext& context) const - { - RPI::Ptr functor = aznew ShaderEnableFunctor; - - functor->m_opacityModeIndex = context.FindMaterialPropertyIndex(Name{ m_opacityMode }); - if (functor->m_opacityModeIndex.IsNull()) - { - return Failure(); - } - AddMaterialPropertyDependency(functor, functor->m_opacityModeIndex); - - functor->m_parallaxEnableIndex = context.FindMaterialPropertyIndex(Name{ m_parallaxEnable }); - if (functor->m_parallaxEnableIndex.IsNull()) - { - return Failure(); - } - AddMaterialPropertyDependency(functor, functor->m_parallaxEnableIndex); - - functor->m_parallaxPdoEnableIndex = context.FindMaterialPropertyIndex(Name{ m_parallaxPdoEnable }); - if (functor->m_parallaxPdoEnableIndex.IsNull()) - { - return Failure(); - } - AddMaterialPropertyDependency(functor, functor->m_parallaxPdoEnableIndex); - - if (!context.CheckShaderIndexValid(m_shadowShaderWithPSIndex)) - { - return Failure(); - } - functor->m_shadowShaderWithPSIndex = m_shadowShaderWithPSIndex; - - if (!context.CheckShaderIndexValid(m_shadowShaderNoPSIndex)) - { - return Failure(); - } - functor->m_shadowShaderNoPSIndex = m_shadowShaderNoPSIndex; - - if (!context.CheckShaderIndexValid(m_depthShaderWithPSIndex)) - { - return Failure(); - } - functor->m_depthShaderWithPSIndex = m_depthShaderWithPSIndex; - - if (!context.CheckShaderIndexValid(m_depthShaderNoPSIndex)) - { - return Failure(); - } - functor->m_depthShaderNoPSIndex = m_depthShaderNoPSIndex; - - if (!context.CheckShaderIndexValid(m_pbrShaderNoEdsIndex)) - { - return Failure(); - } - functor->m_pbrShaderNoEdsIndex = m_pbrShaderNoEdsIndex; - - if (!context.CheckShaderIndexValid(m_pbrShaderWithEdsIndex)) - { - return Failure(); - } - functor->m_pbrShaderWithEdsIndex = m_pbrShaderWithEdsIndex; - if (!context.CheckShaderIndexValid(m_depthShaderTransparentMin)) - { - return Failure(); - } - functor->m_depthShaderTransparentMin = m_depthShaderTransparentMin; - if (!context.CheckShaderIndexValid(m_depthShaderTransparentMax)) - { - return Failure(); - } - functor->m_depthShaderTransparentMax = m_depthShaderTransparentMax; - - return Success(RPI::Ptr(functor)); - } - } -} diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.h b/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.h deleted file mode 100644 index 2d00a4a015..0000000000 --- a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include "./ShaderEnableFunctor.h" -#include - -namespace AZ -{ - namespace Render - { - class ShaderEnableFunctor; - - //! Builds a ShaderEnableFunctor - class ShaderEnableFunctorSourceData final - : public RPI::MaterialFunctorSourceData - { - public: - AZ_RTTI(ShaderEnableFunctorSourceData, "{63775ECB-5C3E-44D3-B175-4537BF76C3A7}", RPI::MaterialFunctorSourceData); - - static void Reflect(ReflectContext* context); - - FunctorResult CreateFunctor(const RuntimeContext& context) const override; - - private: - - AZStd::string m_opacityMode; - AZStd::string m_parallaxEnable; - AZStd::string m_parallaxPdoEnable; - - uint32_t m_shadowShaderNoPSIndex = -1; - uint32_t m_shadowShaderWithPSIndex = -1; - uint32_t m_depthShaderNoPSIndex = -1; - uint32_t m_depthShaderWithPSIndex = -1; - uint32_t m_pbrShaderWithEdsIndex = -1; - uint32_t m_pbrShaderNoEdsIndex = -1; - // The following are used by the light culling system to produce min/max depth bounds - uint32_t m_depthShaderTransparentMin = -1; - uint32_t m_depthShaderTransparentMax = -1; - }; - } -} diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_editor_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_editor_files.cmake index 3a749a4b67..4e7cc9dab3 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_editor_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_editor_files.cmake @@ -24,16 +24,12 @@ set(FILES Source/Material/ConvertEmissiveUnitFunctorSourceData.h Source/Material/MaterialConverterSystemComponent.cpp Source/Material/MaterialConverterSystemComponent.h - Source/Material/ShaderEnableFunctorSourceData.cpp - Source/Material/ShaderEnableFunctorSourceData.h Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.cpp Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.h Source/Material/Transform2DFunctorSourceData.cpp Source/Material/Transform2DFunctorSourceData.h Source/Material/UseTextureFunctorSourceData.cpp Source/Material/UseTextureFunctorSourceData.h - Source/Material/PropertyVisibilityFunctorSourceData.cpp - Source/Material/PropertyVisibilityFunctorSourceData.h Source/Material/DrawListFunctorSourceData.cpp Source/Material/DrawListFunctorSourceData.h ) diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake index 8926b0c19f..91d1587d27 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake @@ -153,16 +153,12 @@ set(FILES Source/LookupTable/LookupTableAsset.cpp Source/Material/ConvertEmissiveUnitFunctor.cpp Source/Material/ConvertEmissiveUnitFunctor.h - Source/Material/ShaderEnableFunctor.cpp - Source/Material/ShaderEnableFunctor.h Source/Material/SubsurfaceTransmissionParameterFunctor.cpp Source/Material/SubsurfaceTransmissionParameterFunctor.h Source/Material/Transform2DFunctor.cpp Source/Material/Transform2DFunctor.h Source/Material/UseTextureFunctor.cpp Source/Material/UseTextureFunctor.h - Source/Material/PropertyVisibilityFunctor.cpp - Source/Material/PropertyVisibilityFunctor.h Source/Material/DrawListFunctor.cpp Source/Material/DrawListFunctor.h Source/Math/GaussianMathFilter.h From 014f715fd88eb51677eea367638ea4ef3d611860 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Wed, 26 May 2021 21:27:31 -0700 Subject: [PATCH 16/41] ATOM-14037 StandardPBR TintedTransparent Opacity Copied tinted transparency opacity mode from EnhancedPBR to StandardPBR. Fixed a bug in EnhancedPBR where Blended opacity didn't work right because the second DrawListOverride functor was stomping on the results of the first DrawListOverride. I removed these functors and made StandardPBR_HandleOpacityMode.lua set the draw list override instead. --- .../Materials/Types/EnhancedPBR.materialtype | 18 --------------- .../Types/EnhancedPBR_ForwardPass.azsl | 10 ++++---- .../Materials/Types/StandardPBR.materialtype | 11 +-------- .../Types/StandardPBR_ForwardPass.azsl | 18 +++++++++++++++ .../Types/StandardPBR_HandleOpacityMode.lua | 3 +++ .../009_Opacity_TintedTransparent.material | 23 +++++++++++++++++++ 6 files changed, 50 insertions(+), 33 deletions(-) create mode 100644 Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_TintedTransparent.material diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index 4c988c590a..36ebb3a0ca 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -1656,24 +1656,6 @@ "file": "StandardPBR_HandleOpacityDoubleSided.lua" } }, - { - "type": "OverrideDrawList", - "args": { - "triggerProperty": "opacity.mode", - "triggerValue": "Blended", - "shaderIndex": 1, - "drawList": "transparent" - } - }, - { - "type": "OverrideDrawList", - "args": { - "triggerProperty": "opacity.mode", - "triggerValue": "TintedTransparent", - "shaderIndex": 1, - "drawList": "transparent" - } - }, { "type": "Lua", "args": { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index 440bb97c4e..a4fcccb5f5 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -267,16 +267,16 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // Directional light shadow coordinates lightingData.shadowCoords = IN.m_shadowCoords; - // ------- Occlusion ------- - - lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); - lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); - // ------- Emissive ------- float2 emissiveUv = IN.m_uv[MaterialSrg::m_emissiveMapUvIndex]; lightingData.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture); + // ------- Occlusion ------- + + lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); + lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); + // ------- Clearcoat ------- // [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype index 038e65a89f..5cc7c933b9 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype @@ -601,7 +601,7 @@ "displayName": "Opacity Mode", "description": "Opacity mode for this texture.", "type": "Enum", - "enumValues": [ "Opaque", "Cutout", "Blended" ], + "enumValues": [ "Opaque", "Cutout", "Blended", "TintedTransparent" ], "defaultValue": "Opaque", "connection": { "type": "ShaderOption", @@ -1387,15 +1387,6 @@ "file": "StandardPBR_HandleOpacityDoubleSided.lua" } }, - { - "type": "OverrideDrawList", - "args": { - "triggerProperty": "opacity.mode", - "triggerValue": "Blended", - "shaderIndex": 1, - "drawList": "transparent" - } - }, { "type": "Lua", "args": { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl index 2667c8123b..10fa3814f3 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl @@ -294,6 +294,24 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse lightingOutput.m_diffuseColor.rgb += lightingOutput.m_specularColor.rgb; // add specular } + else if (o_opacity_mode == OpacityMode::TintedTransparent) + { + // See OpacityMode::Blended above for the basic method. TintedTransparent adds onto the above concept by supporting + // colored alpha. This is currently a very basic calculation that uses the baseColor as a multiplier with strength + // determined by the alpha. We'll modify this later to be more physically accurate and allow surface depth, + // absorption, and interior color to be specified. + // + // The technique uses dual source blending to allow two separate sources to be part of the blending equation + // even though ultimately only a single render target is being written to. m_diffuseColor is render target 0 and + // m_specularColor render target 1, and the blend mode is (dest * source1color) + (source * 1.0). + // + // This means that m_specularColor.rgb (source 1) is multiplied against the destination, then + // m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0. + + lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse + lightingOutput.m_diffuseColor.rgb += lightingOutput.m_specularColor.rgb; // add specular + lightingOutput.m_specularColor.rgb = baseColor * (1.0 - lightingOutput.m_diffuseColor.w); + } else { // Pack factor and quality, drawback: because of precision limit of float16 cannot represent exact 1, maximum representable value is 0.9961 diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua index 541b1ac1ce..20d3ee47ae 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua @@ -60,10 +60,13 @@ function Process(context) if(opacityMode == OpacityMode_Blended) then ConfigureAlphaBlending(context:GetShader(ForwardPassIndex)) + context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent") elseif(opacityMode == OpacityMode_TintedTransparent) then ConfigureDualSourceBlending(context:GetShader(ForwardPassIndex)) + context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent") else ResetAlphaBlending(context:GetShader(ForwardPassIndex)) + context:GetShader(ForwardPassIndex):SetDrawListTagOverride("") -- reset to default draw list end end diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_TintedTransparent.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_TintedTransparent.material new file mode 100644 index 0000000000..1716792af1 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_TintedTransparent.material @@ -0,0 +1,23 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardPBR.materialtype", + "parentMaterial": "", + "propertyLayoutVersion": 3, + "properties": { + "baseColor": { + "color": [ + 0.5906767249107361, + 1.0, + 0.11703670024871826, + 1.0 + ], + "textureMap": "Textures/Default/default_basecolor.tif" + }, + "opacity": { + "alphaSource": "Split", + "factor": 0.75, + "mode": "TintedTransparent", + "textureMap": "TestData/Textures/checker8x8_gray_512.png" + } + } +} \ No newline at end of file From 301bfe34861c0837defdccdc4d04b5b6f741ead2 Mon Sep 17 00:00:00 2001 From: scottr Date: Wed, 26 May 2021 22:03:46 -0700 Subject: [PATCH 17/41] [cpack_installer] replaced raw file(DOWNLOAD ...) for download_file() utility --- cmake/Packaging.cmake | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/cmake/Packaging.cmake b/cmake/Packaging.cmake index 7766d7d0ee..84bad13687 100644 --- a/cmake/Packaging.cmake +++ b/cmake/Packaging.cmake @@ -65,19 +65,32 @@ list(GET _version_componets 0 _major_version) list(GET _version_componets 1 _minor_version) set(_url_version_tag "v${_major_version}.${_minor_version}") +set(_package_url "https://cmake.org/files/${_url_version_tag}/${CPACK_CMAKE_PACKAGE_FILE}") -message(STATUS "Ensuring CMake ${CPACK_DESIRED_CMAKE_VERSION} is avaiable for packaging...") -file(DOWNLOAD - https://cmake.org/files/${_url_version_tag}/${CPACK_CMAKE_PACKAGE_FILE} - ${_cmake_package_dest} +message(STATUS "Ensuring CMake ${CPACK_DESIRED_CMAKE_VERSION} is available for packaging...") +download_file( + URL ${_package_url} + TARGET_FILE ${_cmake_package_dest} + EXPECTED_HASH ${CPACK_CMAKE_PACKAGE_HASH} + RESULTS _results ) +list(GET _results 0 _status_code) -file(SHA256 ${_cmake_package_dest} _package_hash) -if (NOT "${_package_hash}" STREQUAL "${CPACK_CMAKE_PACKAGE_HASH}") +if (${_status_code} EQUAL 0 AND EXISTS ${_cmake_package_dest}) + message(STATUS "-> Package found and verified!") +else() file(REMOVE ${_cmake_package_dest}) - message(FATAL_ERROR "Donwload package of CMake does not match expected hash value. " - "Please double check the properies CPACK_CMAKE_PACKAGE_FILE and CPACK_CMAKE_PACKAGE_HASH " - "before trying again.") + list(REMOVE_AT _results 0) + + set(_error_message "An error occurred, code ${_status_code}. URL ${_package_url} - ${_results}") + + if(${_status_code} EQUAL 1) + string(APPEND _error_message + " Please double check the CPACK_CMAKE_PACKAGE_FILE and " + "CPACK_CMAKE_PACKAGE_HASH properties before trying again.") + endif() + + message(FATAL_ERROR ${_error_message}) endif() install(FILES ${_cmake_package_dest} From b206e7ffe5bb88dc1194dd439c97fae3dbd6b24b Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Thu, 27 May 2021 09:58:58 -0700 Subject: [PATCH 18/41] ATOM-15295 Remove Unnecessary Enable Material Properties The only remaining unnecessary enable flag I found was for the parallax property group. It is removed, and now we just use the texture map and useTexture flag to gate whether the feature is enabled. --- .../Materials/Types/EnhancedPBR.materialtype | 14 ++++---- .../Materials/Types/StandardPBR.materialtype | 14 ++++---- .../Types/StandardPBR_ParallaxState.lua | 32 +++++++++++-------- .../Types/StandardPBR_ShaderEnable.lua | 6 ++-- .../TestData/Materials/ParallaxRock.material | 1 - .../012_Parallax_POM.material | 1 - .../012_Parallax_POM_Cutout.material | 1 - .../100_UvTiling_Parallax_A.material | 1 - .../100_UvTiling_Parallax_B.material | 1 - .../Materials/Bricks038_8K/bricks038.material | 1 - .../Concrete016_8K/Concrete016.material | 3 +- .../Materials/Fabric001_8K/Fabric001.material | 1 - .../Materials/Fabric030_4K/Fabric030.material | 1 - .../PaintedPlaster015.material | 1 - .../Assets/Materials/baseboards.material | 3 +- .../Assets/Materials/crown.material | 1 - .../ConcreteStucco/concrete_stucco.material | 3 +- .../Assets/objects/sponza_mat_arch.material | 3 +- .../objects/sponza_mat_background.material | 3 +- .../Assets/objects/sponza_mat_bricks.material | 3 +- .../objects/sponza_mat_ceiling.material | 3 +- .../objects/sponza_mat_columna.material | 3 +- .../objects/sponza_mat_columnb.material | 3 +- .../objects/sponza_mat_columnc.material | 3 +- .../objects/sponza_mat_details.material | 3 +- .../objects/sponza_mat_flagpole.material | 3 +- .../Assets/objects/sponza_mat_floor.material | 3 +- .../Assets/objects/sponza_mat_leaf.material | 3 +- .../Assets/objects/sponza_mat_lion.material | 1 - .../Assets/objects/sponza_mat_roof.material | 3 +- .../Assets/objects/sponza_mat_vase.material | 3 +- .../objects/sponza_mat_vasehanging.material | 3 +- .../objects/sponza_mat_vaseround.material | 3 +- 33 files changed, 72 insertions(+), 59 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index 36ebb3a0ca..4d13663aae 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -933,13 +933,6 @@ } ], "parallax": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the parallax feature.", - "type": "Bool", - "defaultValue": false - }, { "id": "textureMap", "displayName": "Texture Map", @@ -950,6 +943,13 @@ "id": "m_depthMap" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, { "id": "textureMapUv", "displayName": "UV", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype index 5cc7c933b9..ca3e5e1ce4 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype @@ -879,13 +879,6 @@ } ], "parallax": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the parallax feature.", - "type": "Bool", - "defaultValue": false - }, { "id": "textureMap", "displayName": "Texture Map", @@ -896,6 +889,13 @@ "id": "m_depthMap" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, { "id": "textureMapUv", "displayName": "UV", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua index e6689da327..53d6334f28 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua @@ -13,7 +13,7 @@ ---------------------------------------------------------------------------------------------------- function GetMaterialPropertyDependencies() - return {"parallax.enable", "parallax.textureMap"} + return {"parallax.textureMap", "parallax.useTexture"} end function GetShaderOptionDependencies() @@ -21,27 +21,31 @@ function GetShaderOptionDependencies() end function Process(context) - local enable = context:GetMaterialPropertyValue_bool("parallax.enable") local textureMap = context:GetMaterialPropertyValue_Image("parallax.textureMap") + local useTexture = context:GetMaterialPropertyValue_bool("parallax.useTexture") + local enable = textureMap ~= nil and useTexture context:SetShaderOptionValue_bool("o_parallax_feature_enabled", enable) - context:SetShaderOptionValue_bool("o_useDepthMap", enable and textureMap ~= nil) + context:SetShaderOptionValue_bool("o_useDepthMap", enable) end function ProcessEditor(context) - local enable = context:GetMaterialPropertyValue_bool("parallax.enable") - - if enable then - context:SetMaterialPropertyVisibility("parallax.textureMap", MaterialPropertyVisibility_Enabled) - else - context:SetMaterialPropertyVisibility("parallax.textureMap", MaterialPropertyVisibility_Hidden) - end - local textureMap = context:GetMaterialPropertyValue_Image("parallax.textureMap") - local visibility = MaterialPropertyVisibility_Enabled - if(not enable or textureMap == nil) then - visibility = MaterialPropertyVisibility_Hidden + + if textureMap ~= nil then + context:SetMaterialPropertyVisibility("parallax.useTexture", MaterialPropertyVisibility_Enabled) + else + context:SetMaterialPropertyVisibility("parallax.useTexture", MaterialPropertyVisibility_Hidden) end + local useTexture = context:GetMaterialPropertyValue_bool("parallax.useTexture") + + local visibility = MaterialPropertyVisibility_Enabled + if(textureMap == nil) then + visibility = MaterialPropertyVisibility_Hidden + elseif not useTexture then + visibility = MaterialPropertyVisibility_Disabled + end + context:SetMaterialPropertyVisibility("parallax.factor", visibility) context:SetMaterialPropertyVisibility("parallax.offset", visibility) context:SetMaterialPropertyVisibility("parallax.showClipping", visibility) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua index 26c163d61b..b245fde3df 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua @@ -13,7 +13,7 @@ ---------------------------------------------------------------------------------------------------- function GetMaterialPropertyDependencies() - return {"opacity.mode", "parallax.enable", "parallax.pdo"} + return {"opacity.mode", "parallax.textureMap", "parallax.useTexture", "parallax.pdo"} end OpacityMode_Opaque = 0 @@ -37,7 +37,9 @@ end function Process(context) local opacityMode = context:GetMaterialPropertyValue_enum("opacity.mode") - local parallaxEnabled = context:GetMaterialPropertyValue_bool("parallax.enable") + local displacementMap = context:GetMaterialPropertyValue_Image("parallax.textureMap") + local useDisplacementMap = context:GetMaterialPropertyValue_bool("parallax.useTexture") + local parallaxEnabled = displacementMap ~= nil and useDisplacementMap local parallaxPdoEnabled = context:GetMaterialPropertyValue_bool("parallax.pdo") local depthPass = context:GetShaderByTag("DepthPass") diff --git a/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material b/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material index 4c3a925e52..c9276216eb 100644 --- a/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material +++ b/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material @@ -17,7 +17,6 @@ "textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg" }, "parallax": { - "enable": true, "algorithm": "POM", "factor": 0.03, "quality": "High", diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM.material index a94d90d04d..ed070d5de2 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM.material @@ -8,7 +8,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.02500000037252903, "quality": "High", "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_disp.png" diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material index 21f873fe1a..f5ec0e8287 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material @@ -13,7 +13,6 @@ "textureMap": "TestData/Textures/checker8x8_512.png" }, "parallax": { - "enable": true, "factor": 0.10000000149011612, "quality": "High", "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_disp.png" diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_A.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_A.material index 7bf12e5358..b3e69212db 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_A.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_A.material @@ -13,7 +13,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.10000000149011612, "quality": "High", "textureMap": "TestData/Objects/cube/cube_diff.tif" diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_B.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_B.material index 4b9f233a85..3d52f3b9e6 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_B.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_B.material @@ -13,7 +13,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.05000000074505806, "quality": "High", "textureMap": "TestData/Objects/cube/cube_diff.tif" diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material index 25e29b55e5..82b1cdb590 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material @@ -26,7 +26,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.02500000037252903, "pdo": true, "quality": "Ultra", diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016.material index 336d479b30..03fb0ea5be 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016.material @@ -31,7 +31,8 @@ "algorithm": "ContactRefinement", "factor": 0.019999999552965165, "quality": "Ultra", - "textureMap": "Materials/Concrete016_8K/Concrete016_8K_Displacement.png" + "textureMap": "Materials/Concrete016_8K/Concrete016_8K_Displacement.png", + "useTexture": false }, "roughness": { "textureMap": "Materials/Concrete016_8K/Concrete016_8K_Roughness.png" diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001.material index 72610e8bb6..7d8c3d5142 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001.material @@ -20,7 +20,6 @@ }, "parallax": { "algorithm": "ContactRefinement", - "enable": true, "factor": 0.004999999888241291, "quality": "Ultra", "textureMap": "Materials/Fabric001_8K/Fabric001_8K_Displacement.png" diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030.material index 458ab811b6..493bfab455 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030.material @@ -20,7 +20,6 @@ }, "parallax": { "algorithm": "ContactRefinement", - "enable": true, "factor": 0.0020000000949949028, "pdo": true, "quality": "Medium", diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material index 57163f520d..a2bb2c7704 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material @@ -19,7 +19,6 @@ }, "parallax": { "algorithm": "ContactRefinement", - "enable": true, "factor": 0.009999999776482582, "pdo": true, "quality": "Ultra", diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material index 625d872475..f75490c2ad 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material @@ -30,7 +30,8 @@ "factor": 0.02500000037252903, "pdo": true, "quality": "Ultra", - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_Displacement.png" + "textureMap": "Materials/Bricks038_8K/Bricks038_8K_Displacement.png", + "useTexture": false }, "roughness": { "factor": 0.4343433976173401, diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material index e3c6d9eae6..d7e2050dbd 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material @@ -22,7 +22,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.02500000037252903, "pdo": true, "quality": "Ultra", diff --git a/Gems/AtomContent/ReferenceMaterials/Assets/Materials/ConcreteStucco/concrete_stucco.material b/Gems/AtomContent/ReferenceMaterials/Assets/Materials/ConcreteStucco/concrete_stucco.material index ab9f366ff6..d4e2016022 100644 --- a/Gems/AtomContent/ReferenceMaterials/Assets/Materials/ConcreteStucco/concrete_stucco.material +++ b/Gems/AtomContent/ReferenceMaterials/Assets/Materials/ConcreteStucco/concrete_stucco.material @@ -19,7 +19,8 @@ }, "parallax": { "factor": 0.0010101000079885126, - "textureMap": "Materials/ConcreteStucco/concrete_stucco_height.jpg" + "textureMap": "Materials/ConcreteStucco/concrete_stucco_height.jpg", + "useTexture": false }, "specularF0": { "factor": 0.5050504803657532 diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material index 1102fb150a..d95e84121c 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material @@ -41,7 +41,8 @@ "factor": 0.050999999046325687, "pdo": true, "quality": "High", - "textureMap": "Textures/arch_1k_height.png" + "textureMap": "Textures/arch_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/arch_1k_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material index c1853250d7..710f790419 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material @@ -47,7 +47,8 @@ "factor": 0.03099999949336052, "pdo": true, "quality": "High", - "textureMap": "Textures/background_1k_height.png" + "textureMap": "Textures/background_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/background_1k_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material index a269098b4d..26d64c7db9 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material @@ -46,7 +46,8 @@ "algorithm": "ContactRefinement", "factor": 0.03500000014901161, "quality": "Medium", - "textureMap": "Textures/bricks_1k_height.png" + "textureMap": "Textures/bricks_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/bricks_1k_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material index 94225cd00e..95d08d398b 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material @@ -48,7 +48,8 @@ "factor": 0.019999999552965165, "pdo": true, "quality": "Medium", - "textureMap": "Textures/ceiling_1k_height.png" + "textureMap": "Textures/ceiling_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/ceiling_1k_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material index 8f1cea8649..cc1f685c7c 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material @@ -47,7 +47,8 @@ "factor": 0.017000000923871995, "pdo": true, "quality": "High", - "textureMap": "Textures/columnA_1k_height.png" + "textureMap": "Textures/columnA_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/columnA_1k_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material index ac474d7e76..a1e8747f65 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material @@ -46,7 +46,8 @@ "factor": 0.020999999716877939, "pdo": true, "quality": "High", - "textureMap": "Textures/columnB_1k_height.png" + "textureMap": "Textures/columnB_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/columnB_1k_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material index 81fd03fc4a..6edbfde47c 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material @@ -47,7 +47,8 @@ "factor": 0.014000000432133675, "pdo": true, "quality": "High", - "textureMap": "Textures/columnC_1k_height.png" + "textureMap": "Textures/columnC_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/columnC_1k_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material index fde599fd4c..1b66a51ec0 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material @@ -38,7 +38,8 @@ "algorithm": "POM", "factor": 0.02500000037252903, "pdo": true, - "textureMap": "Textures/details_1k_height.png" + "textureMap": "Textures/details_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/details_1k_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material index e50e8a0ed2..19010d66e5 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material @@ -41,7 +41,8 @@ "factor": 0.014000000432133675, "pdo": true, "quality": "High", - "textureMap": "Textures/flagpole_1k_height.png" + "textureMap": "Textures/flagpole_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/flagpole_1k_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material index 064a2b24a6..bee92e0edb 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material @@ -43,7 +43,8 @@ "algorithm": "POM", "factor": 0.012000000104308129, "pdo": true, - "textureMap": "Textures/floor_1k_height.png" + "textureMap": "Textures/floor_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/floor_1k_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material index 269e1e5684..ac326ae935 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material @@ -42,7 +42,8 @@ "mode": "Cutout" }, "parallax": { - "textureMap": "Textures/thorn_height.png" + "textureMap": "Textures/thorn_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/thorn_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material index 8dc4852b03..b1f78aa33f 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material @@ -38,7 +38,6 @@ }, "parallax": { "algorithm": "ContactRefinement", - "enable": true, "factor": 0.009999999776482582, "pdo": true, "quality": "Ultra", diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material index 0a7246703c..a3e066a438 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material @@ -35,7 +35,8 @@ "algorithm": "ContactRefinement", "factor": 0.019999999552965165, "quality": "Medium", - "textureMap": "Textures/roof_1k_height.png" + "textureMap": "Textures/roof_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/roof_1k_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material index 77adc798a0..dea9aa2a8a 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material @@ -41,7 +41,8 @@ "factor": 0.027000000700354577, "pdo": true, "quality": "High", - "textureMap": "Textures/vase_1k_height.png" + "textureMap": "Textures/vase_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/vase_1k_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material index 22e78f03ae..b2a342dd76 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material @@ -41,7 +41,8 @@ "factor": 0.04600000008940697, "pdo": true, "quality": "High", - "textureMap": "Textures/vaseHanging_1k_height.png" + "textureMap": "Textures/vaseHanging_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/vaseHanging_1k_roughness.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material index c773146b51..fba07379c0 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material @@ -45,7 +45,8 @@ "factor": 0.019999999552965165, "pdo": true, "quality": "High", - "textureMap": "Textures/vaseRound_1k_height.png" + "textureMap": "Textures/vaseRound_1k_height.png", + "useTexture": false }, "roughness": { "textureMap": "Textures/vaseRound_1k_roughness.png" From c2822a4063d3512166fe467c6fdaa43488885de3 Mon Sep 17 00:00:00 2001 From: guthadam Date: Thu, 27 May 2021 13:17:51 -0500 Subject: [PATCH 19/41] ATOM-15649 sorting material types in create material dialog --- .../Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp index 6a4bb8c0f4..887019787b 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp @@ -71,6 +71,8 @@ namespace MaterialEditor QObject::connect(m_ui->m_materialTypeComboBox, static_cast(&QComboBox::currentIndexChanged), this, [this]() { UpdateMaterialTypeSelection(); }); QObject::connect(m_ui->m_materialTypeComboBox, &QComboBox::currentTextChanged, this, [this]() { UpdateMaterialTypeSelection(); }); + m_ui->m_materialTypeComboBox->model()->sort(0, Qt::AscendingOrder); + // Select the default material type from settings auto settings = AZ::UserSettings::CreateFind(AZ::Crc32("MaterialDocumentSettings"), AZ::UserSettings::CT_GLOBAL); From 85222130d4137d79c994b273f88dc7c39fc12929 Mon Sep 17 00:00:00 2001 From: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> Date: Thu, 27 May 2021 13:56:19 -0700 Subject: [PATCH 20/41] LYN-4007 Editor crashes when entering the Game Mode with two Box Shape entities with Game View enabled (#974) The crash was caused by using gpu query across command lists. --- .../Code/Source/RPI.Public/GpuQuery/Query.cpp | 12 --------- .../Source/RPI.Public/Pass/RenderPass.cpp | 26 ++++++++++++++++--- .../RPI/Code/Tests/System/GpuQueryTests.cpp | 12 ++++++--- ...AtomViewportDisplayInfoSystemComponent.cpp | 8 +++--- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/Query.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/Query.cpp index 227e096594..1d6e8cdc65 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/Query.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/Query.cpp @@ -96,12 +96,6 @@ namespace AZ return QueryResultCode::Fail; } - // Limit calling BeginQuery() to the first CommandList in the array. - if (context.GetCommandListIndex() != 0) - { - return QueryResultCode::Success; - } - const auto rhiQueryIndices = GetRhiQueryIndicesFromCurrentFrame(); if (!rhiQueryIndices) { @@ -124,12 +118,6 @@ namespace AZ return QueryResultCode::Fail; } - // Limit calling EndQuery() to the last CommandList in the array. - if (context.GetCommandListIndex() != context.GetCommandListCount() - 1) - { - return QueryResultCode::Success; - } - // Validate that the queries are recorded for the same scope. if (m_cachedScopeId != context.GetScopeId()) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp index 9c6a95e582..3a2a556429 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp @@ -522,8 +522,11 @@ namespace AZ } }; - ExecuteOnTimestampQuery(beginQuery); - ExecuteOnPipelineStatisticsQuery(beginQuery); + if (context.GetCommandListIndex() == 0) + { + ExecuteOnTimestampQuery(beginQuery); + ExecuteOnPipelineStatisticsQuery(beginQuery); + } } void RenderPass::EndScopeQuery(const RHI::FrameGraphExecuteContext& context) @@ -533,8 +536,23 @@ namespace AZ query->EndQuery(context); }; - ExecuteOnTimestampQuery(endQuery); - ExecuteOnPipelineStatisticsQuery(endQuery); + // This scopy query implmentation should be replaced by + // [ATOM-5407] [RHI][Core] - Add GPU timestamp and pipeline statistic support for scopes + + // For timestamp query, it's okay to execute across different command lists + if (context.GetCommandListIndex() == context.GetCommandListCount() - 1) + { + ExecuteOnTimestampQuery(endQuery); + } + // For all the other types of queries except timestamp, the query start and end has to be in the same command list + // Here only tracks the PipelineStatistics for the first command list due to that we don't know how many queries are + // needed when AddScopeQueryToFrameGraph is called. + // This implementation leads to an issue that we may not get accurate pipeline statistic data + // for passes which were executed with more than one command list + if (context.GetCommandListIndex() == 0) + { + ExecuteOnPipelineStatisticsQuery(endQuery); + } } void RenderPass::ReadbackScopeQueryResults() diff --git a/Gems/Atom/RPI/Code/Tests/System/GpuQueryTests.cpp b/Gems/Atom/RPI/Code/Tests/System/GpuQueryTests.cpp index e55ec8012b..98ff6befdd 100644 --- a/Gems/Atom/RPI/Code/Tests/System/GpuQueryTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/System/GpuQueryTests.cpp @@ -159,7 +159,9 @@ namespace UnitTest const uint32_t ResultSize = sizeof(uint64_t); uint64_t mockData; - const RHI::FrameGraphExecuteContext::Descriptor desc = {}; + RHI::FrameGraphExecuteContext::Descriptor desc = {}; + uint64_t dummyCommandList; + desc.m_commandList = reinterpret_cast(&dummyCommandList); RHI::FrameGraphExecuteContext context(desc); RHI::Scope scope; @@ -209,7 +211,9 @@ namespace UnitTest const uint32_t ResultSize = sizeof(uint64_t) * 4u; uint64_t mockData; - const RHI::FrameGraphExecuteContext::Descriptor desc = {}; + RHI::FrameGraphExecuteContext::Descriptor desc = {}; + uint64_t dummyCommandList; + desc.m_commandList = reinterpret_cast(&dummyCommandList); RHI::FrameGraphExecuteContext context(desc); RHI::Scope scope; @@ -273,7 +277,9 @@ namespace UnitTest const uint32_t ResultSize = sizeof(uint64_t) * 2u; uint64_t mockData; - const RHI::FrameGraphExecuteContext::Descriptor desc = {}; + RHI::FrameGraphExecuteContext::Descriptor desc = {}; + uint64_t dummyCommandList; + desc.m_commandList = reinterpret_cast(&dummyCommandList); RHI::FrameGraphExecuteContext context(desc); RHI::Scope scope; diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp index 672c26a9ab..7d830b4ca9 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp @@ -18,10 +18,11 @@ #include #include +#include +#include #include #include #include -#include #include #include @@ -146,7 +147,7 @@ namespace AZ::Render if (m_updateRootPassQuery) { - if (auto rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass()) + if (auto rootPass = viewportContext->GetCurrentPipeline()->GetRootPass()) { rootPass->SetPipelineStatisticsQueryEnabled(displayLevel != AtomBridge::ViewportInfoDisplayState::CompactInfo); m_updateRootPassQuery = false; @@ -226,7 +227,8 @@ namespace AZ::Render void AtomViewportDisplayInfoSystemComponent::DrawPassInfo() { - auto rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass(); + AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); + auto rootPass = viewportContext->GetCurrentPipeline()->GetRootPass(); const RPI::PipelineStatisticsResult stats = rootPass->GetLatestPipelineStatisticsResult(); AZStd::function)> containingPassCount = [&containingPassCount](const AZ::RPI::Ptr pass) { From 0d7c23641aca8db473c310a25c8e707df252f9c3 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Thu, 27 May 2021 14:12:29 -0700 Subject: [PATCH 21/41] Fix missing space betweek arguments causing dxc commands with additional args to fail (#1003) --- Gems/Atom/RHI/Code/Source/RHI.Edit/ShaderCompilerArguments.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RHI/Code/Source/RHI.Edit/ShaderCompilerArguments.cpp b/Gems/Atom/RHI/Code/Source/RHI.Edit/ShaderCompilerArguments.cpp index 3a04bf6b88..09cd1c125e 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Edit/ShaderCompilerArguments.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Edit/ShaderCompilerArguments.cpp @@ -164,7 +164,7 @@ namespace AZ arguments += " -Zi"; // Generate debug information arguments += " -Zss"; // Compute Shader Hash considering source information } - arguments += m_dxcAdditionalFreeArguments; + arguments += " " + m_dxcAdditionalFreeArguments; return arguments; } } From be54df8c1e4dbb85e48e3b02cef89d385b5ab4f7 Mon Sep 17 00:00:00 2001 From: gallowj Date: Thu, 27 May 2021 17:04:23 -0500 Subject: [PATCH 22/41] Added a required CC license for Sponza content --- Gems/AtomContent/Sponza/Assets/license.txt | 8 ++++++++ Gems/AtomContent/Sponza/Assets/stub | 0 2 files changed, 8 insertions(+) create mode 100644 Gems/AtomContent/Sponza/Assets/license.txt delete mode 100644 Gems/AtomContent/Sponza/Assets/stub diff --git a/Gems/AtomContent/Sponza/Assets/license.txt b/Gems/AtomContent/Sponza/Assets/license.txt new file mode 100644 index 0000000000..e303d8c767 --- /dev/null +++ b/Gems/AtomContent/Sponza/Assets/license.txt @@ -0,0 +1,8 @@ +The content in this gem "O3DE\Gems\AtomContent\Sponza" is ported +from the original source, and modified for the O3DE Engine and Atom Renderer. + +The original "Crytek Sponza" scene data can be downloaded from the +"McGuire Computer Graphics Archive": https://casual-effects.com/data/ + +The original content is under the "CC BY 3.0" License: +https://creativecommons.org/licenses/by/3.0/ \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/stub b/Gems/AtomContent/Sponza/Assets/stub deleted file mode 100644 index e69de29bb2..0000000000 From 5e87250f6794759c469006f325f68482d8c8e9d5 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Thu, 27 May 2021 16:31:30 -0700 Subject: [PATCH 23/41] Fix viewport icon rendering on high DPI devices (#1006) * Clarify ViewportWorldToScreen being in widget space and add DeviceScalingFactor * -Fix viewport icons being draw wrong on high DPI displays -Fix loading viewport icons from absolute paths, which * Address review feedback, fix build --- .../ViewportInteraction.h | 1 + .../Source/ViewportInteraction.cpp | 7 ++- .../Viewport/ViewportMessages.h | 7 ++- Code/Sandbox/Editor/RenderViewport.h | 1 + .../Viewport/RenderViewportWidget.h | 1 + .../Source/Viewport/RenderViewportWidget.cpp | 8 +++- ...tomViewportDisplayIconsSystemComponent.cpp | 46 +++++++++++++------ .../AtomViewportDisplayIconsSystemComponent.h | 2 +- 8 files changed, 53 insertions(+), 20 deletions(-) diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h index 884562d7e8..28971dc779 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h @@ -41,6 +41,7 @@ namespace AzManipulatorTestFramework AZStd::optional ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) override; AZStd::optional ViewportScreenToWorldRay( const AzFramework::ScreenPoint& screenPosition) override; + float DeviceScalingFactor() override; private: // ViewportInteractionRequestBus ... bool GridSnappingEnabled(); diff --git a/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp b/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp index ebef9dea30..7d32187a74 100644 --- a/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp +++ b/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp @@ -127,4 +127,9 @@ namespace AzManipulatorTestFramework { return {}; } -} // namespace AzManipulatorTestFramework + + float ViewportInteraction::DeviceScalingFactor() + { + return 1.0f; + } +}// namespace AzManipulatorTestFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h index 8e91dc945d..91eee18cb7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h @@ -165,15 +165,18 @@ namespace AzToolsFramework virtual bool AngleSnappingEnabled() = 0; /// Return the angle snapping/step size. virtual float AngleStep() = 0; - /// Transform a point in world space to screen space coordinates. + /// Transform a point in world space to screen space coordinates in Qt Widget space. + /// Multiply by DeviceScalingFactor to get the position in viewport pixel space. virtual AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition) = 0; - /// Transform a point in screen space coordinates to a vector in world space based on clip space depth. + /// Transform a point from Qt widget screen space to world space based on the given clip space depth. /// Depth specifies a relative camera depth to project in the range of [0.f, 1.f]. /// Returns the world space position if successful. virtual AZStd::optional ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) = 0; /// Casts a point in screen space to a ray in world space originating from the viewport camera frustum's near plane. /// Returns a ray containing the ray's origin and a direction normal, if successful. virtual AZStd::optional ViewportScreenToWorldRay(const AzFramework::ScreenPoint& screenPosition) = 0; + /// Gets the DPI scaling factor that translates Qt widget space into viewport pixel space. + virtual float DeviceScalingFactor() = 0; protected: ~ViewportInteractionRequests() = default; diff --git a/Code/Sandbox/Editor/RenderViewport.h b/Code/Sandbox/Editor/RenderViewport.h index d70dd59b98..b45c92b1c8 100644 --- a/Code/Sandbox/Editor/RenderViewport.h +++ b/Code/Sandbox/Editor/RenderViewport.h @@ -200,6 +200,7 @@ public: { return {}; } + float DeviceScalingFactor() override { return 1.0f; } // AzToolsFramework::ViewportFreezeRequestBus bool IsViewportInputFrozen() override; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h index a41c8221f0..f2c120dbcd 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h @@ -98,6 +98,7 @@ namespace AtomToolsFramework AZStd::optional ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) override; AZStd::optional ViewportScreenToWorldRay( const AzFramework::ScreenPoint& screenPosition) override; + float DeviceScalingFactor() override; //! Set interface for providing viewport specific settings (e.g. snapping properties). void SetViewportSettings(const AzToolsFramework::ViewportInteraction::ViewportSettings* viewportSettings); diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp index cee178c724..35edb3af5b 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp @@ -313,8 +313,7 @@ namespace AtomToolsFramework // Scale the size by the DPI of the platform to // get the proper size in pixels. const QSize uiWindowSize = size(); - const qreal deficePixelRatio = devicePixelRatioF(); - const QSize windowSize = uiWindowSize * deficePixelRatio; + const QSize windowSize = uiWindowSize * devicePixelRatioF(); const AzFramework::NativeWindowHandle windowId = reinterpret_cast(winId()); AzFramework::WindowNotificationBus::Event(windowId, &AzFramework::WindowNotifications::OnWindowResized, windowSize.width(), windowSize.height()); @@ -465,6 +464,11 @@ namespace AtomToolsFramework return AzToolsFramework::ViewportInteraction::ProjectedViewportRay{rayOrigin, rayDirection}; } + float RenderViewportWidget::DeviceScalingFactor() + { + return aznumeric_cast(devicePixelRatioF()); + } + AzFramework::ScreenPoint RenderViewportWidget::ViewportCursorScreenPosition() { return AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(m_mousePosition.toPoint()); diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp index dce83c3072..5fe8c50350 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -145,12 +146,24 @@ namespace AZ::Render } // Initialize our shader - auto viewportSize = viewportContext->GetViewportSize(); + AZ::Vector2 viewportSize; + { + AzFramework::WindowSize viewportWindowSize = viewportContext->GetViewportSize(); + viewportSize = AZ::Vector2{aznumeric_cast(viewportWindowSize.m_width), aznumeric_cast(viewportWindowSize.m_height)}; + } AZ::Data::Instance drawSrg = dynamicDraw->NewDrawSrg(); - drawSrg->SetConstant(m_viewportSizeIndex, AZ::Vector2(aznumeric_cast(viewportSize.m_width), aznumeric_cast(viewportSize.m_height))); + drawSrg->SetConstant(m_viewportSizeIndex,viewportSize); drawSrg->SetImageView(m_textureParameterIndex, image->GetImageView()); drawSrg->Compile(); + // Scale icons by screen DPI + float scalingFactor = 1.0f; + { + using ViewportRequestBus = AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus; + ViewportRequestBus::EventResult( + scalingFactor, drawParameters.m_viewport, &ViewportRequestBus::Events::DeviceScalingFactor); + } + AZ::Vector3 screenPosition; if (drawParameters.m_positionSpace == CoordinateSpace::ScreenSpace) { @@ -158,9 +171,11 @@ namespace AZ::Render } else if (drawParameters.m_positionSpace == CoordinateSpace::WorldSpace) { - using ViewportRequestBus = AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus; - AzFramework::ScreenPoint position; - ViewportRequestBus::EventResult(position, drawParameters.m_viewport, &ViewportRequestBus::Events::ViewportWorldToScreen, drawParameters.m_position); + // Calculate our screen space position using the viewport size + // We want this instead of RenderViewportWidget::WorldToScreen which works in QWidget virtual coordinate space + AzFramework::ScreenPoint position = AzFramework::WorldToScreen( + drawParameters.m_position, viewportContext->GetCameraViewMatrix(), viewportContext->GetCameraProjectionMatrix(), + viewportSize); screenPosition.SetX(aznumeric_cast(position.m_x)); screenPosition.SetY(aznumeric_cast(position.m_y)); } @@ -179,8 +194,8 @@ namespace AZ::Render { Vertex vertex; screenPosition.StoreToFloat3(vertex.m_position); - vertex.m_position[0] += offsetX * drawParameters.m_size.GetX(); - vertex.m_position[1] += offsetY * drawParameters.m_size.GetY(); + vertex.m_position[0] += offsetX * drawParameters.m_size.GetX() * scalingFactor; + vertex.m_position[1] += offsetY * drawParameters.m_size.GetY() * scalingFactor; vertex.m_color = drawParameters.m_color.ToU32(); vertex.m_uv[0] = u; vertex.m_uv[1] = v; @@ -197,8 +212,15 @@ namespace AZ::Render dynamicDraw->DrawIndexed(&vertices, vertices.size(), &indices, indices.size(), RHI::IndexFormat::Uint16, drawSrg); } - QString AtomViewportDisplayIconsSystemComponent::FindAssetPath(const QString& sourceRelativePath) const + QString AtomViewportDisplayIconsSystemComponent::FindAssetPath(const QString& path) const { + // If we get an absolute path, just use it. + QFileInfo pathInfo(path); + if (pathInfo.isAbsolute()) + { + return path; + } + bool found = false; AZStd::vector scanFolders; AzToolsFramework::AssetSystemRequestBus::BroadcastResult( @@ -212,9 +234,9 @@ namespace AZ::Render for (const auto& folder : scanFolders) { QDir dir(folder.data()); - if (dir.exists(sourceRelativePath)) + if (dir.exists(path)) { - return dir.absoluteFilePath(sourceRelativePath); + return dir.absoluteFilePath(path); } } @@ -256,10 +278,6 @@ namespace AZ::Render AzToolsFramework::EditorViewportIconDisplayInterface::IconId AtomViewportDisplayIconsSystemComponent::GetOrLoadIconForPath( AZStd::string_view path) { - AZ_Error( - "AtomViewportDisplayIconsSystemComponent", AzFramework::StringFunc::Path::IsRelative(path.data()), - "GetOrLoadIconForPath assumes that it will always be given a relative path, but got '%s'", path.data()); - // Check our cache to see if the image is already loaded auto existingEntryIt = AZStd::find_if(m_iconData.begin(), m_iconData.end(), [&path](const auto& iconData) { diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h index 0c7366f23b..b44957b51d 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h @@ -61,7 +61,7 @@ namespace AZ static constexpr QSize MinimumRenderedSvgSize = QSize(128, 128); static constexpr QImage::Format QtImageFormat = QImage::Format_RGBA8888; - QString FindAssetPath(const QString& sourceRelativePath) const; + QString FindAssetPath(const QString& path) const; QImage RenderSvgToImage(const QString& svgPath) const; AZ::Data::Instance ConvertToAtomImage(AZ::Uuid assetId, QImage image) const; From 9435305f01bce2bb88fcabb143654bf02edeeb61 Mon Sep 17 00:00:00 2001 From: Terry Michaels <81711813+tjmichaels@users.noreply.github.com> Date: Thu, 27 May 2021 19:31:32 -0500 Subject: [PATCH 24/41] Make entity creation via asset drag and drop properly create an entity so it works with prefabs correctly (#1010) --- .../AzAssetBrowserRequestHandler.cpp | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp index c8bd157b65..e0ba106875 100644 --- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp +++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp @@ -137,8 +137,20 @@ namespace AzAssetBrowserRequestHandlerPrivate entityName = AZStd::string::format("Entity%d", GetIEditor()->GetObjectManager()->GetObjectCount()); } - AZ::Entity* newEntity = aznew AZ::Entity(entityName.c_str()); - EditorEntityContextRequestBus::Broadcast(&EditorEntityContextRequests::AddRequiredComponents, *newEntity); + AZ::EntityId targetEntityId; + EditorRequests::Bus::BroadcastResult(targetEntityId, &EditorRequests::CreateNewEntityAtPosition, worldTransform.GetTranslation(), AZ::EntityId()); + + AZ::Entity* newEntity = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(newEntity, &AZ::ComponentApplicationRequests::FindEntity, targetEntityId); + + if (newEntity == nullptr) + { + return; + } + + newEntity->SetName(entityName); + + newEntity->Deactivate(); // Create component. AZ::Component* newComponent = newEntity->CreateComponent(componentTypeId); @@ -151,15 +163,7 @@ namespace AzAssetBrowserRequestHandlerPrivate newEntity->AddComponent(newComponent); } - // Set entity position. - auto* transformComponent = newEntity->FindComponent(); - if (transformComponent) - { - transformComponent->SetWorldTM(worldTransform); - } - - // Add the entity to the editor context, which activates it and creates the sandbox object. - EditorEntityContextRequestBus::Broadcast(&EditorEntityContextRequests::AddEditorEntity, newEntity); + newEntity->Activate(); // set asset after components have been activated in AddEditorEntity method if (newComponent) From 25dc42e298eefde477909f4ccd11e4cfd15667ec Mon Sep 17 00:00:00 2001 From: galibzon <66021303+galibzon@users.noreply.github.com> Date: Thu, 27 May 2021 21:45:19 -0500 Subject: [PATCH 25/41] [ATOM-15600] Fix cpu over usage when loading shader variant assets. (#1014) This is a temporary fix, in the future ShaderVariantAsyncLoader will use OnCatalogAssetRemoved()/ OnCatalogAssetAdded(). Signed-off-by: garrieta --- .../Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp index 6579e6a98d..3fc2bbd197 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp @@ -150,10 +150,7 @@ namespace AZ } } - if (!shaderVariantTreePendingRequests.empty() || !shaderVariantPendingRequests.empty()) - { - AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(1000)); - } + AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(1000)); } } From 051384e9a74dcdb795eb1412561528f82f58757d Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Thu, 27 May 2021 20:13:45 -0700 Subject: [PATCH 26/41] Remove AZ_TRAIT_DISABLE_ASSET_JOB_PARALLEL_TESTS from Linux traits (#1018) --- .../Framework/AzTest/AzTest/Platform/Linux/AzTest_Traits_Linux.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Code/Framework/AzTest/AzTest/Platform/Linux/AzTest_Traits_Linux.h b/Code/Framework/AzTest/AzTest/Platform/Linux/AzTest_Traits_Linux.h index 0090ce066b..855b4fe416 100644 --- a/Code/Framework/AzTest/AzTest/Platform/Linux/AzTest_Traits_Linux.h +++ b/Code/Framework/AzTest/AzTest/Platform/Linux/AzTest_Traits_Linux.h @@ -39,4 +39,3 @@ #define AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_EDITOR_TESTS true #define AZ_TRAIT_DISABLE_FAILED_METRICS_TESTS true -#define AZ_TRAIT_DISABLE_ASSET_JOB_PARALLEL_TESTS true From 5bb55ac1c7723512d24ce610ebb0ead2554ee99c Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Fri, 28 May 2021 07:38:05 +0200 Subject: [PATCH 27/41] [LYN-2514] Optimizing for new window dimensions (#990) --- .../Resources/ProjectManager.qss | 29 ++++++++++++++++++- .../GemCatalog/GemCatalogHeaderWidget.cpp | 8 +++-- .../Source/GemCatalog/GemFilterWidget.cpp | 13 +++++---- .../Source/GemCatalog/GemInspector.cpp | 17 ++++++----- .../Source/GemCatalog/GemItemDelegate.cpp | 14 ++++----- .../Source/GemCatalog/GemItemDelegate.h | 26 ++++++++--------- .../Source/GemCatalog/GemListHeaderWidget.cpp | 11 +++---- .../ProjectManager/Source/LinkWidget.cpp | 4 +-- .../Tools/ProjectManager/Source/TagWidget.cpp | 6 ++-- 9 files changed, 80 insertions(+), 48 deletions(-) diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qss b/Code/Tools/ProjectManager/Resources/ProjectManager.qss index 5eb92964dd..a85b911c15 100644 --- a/Code/Tools/ProjectManager/Resources/ProjectManager.qss +++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qss @@ -336,4 +336,31 @@ QTabBar::tab:pressed max-width:210px;; min-height:278px; max-height:278px; -} \ No newline at end of file +} + +/************** Gem Catalog **************/ + +#GemCatalogTitle { + font-size: 18px; +} + +/************** Gem Catalog (Inspector) **************/ + +#GemCatalogInspector { + background-color: #444444; +} + +/************** Gem Catalog (Filter/left pane) **************/ + +#GemCatalogFilterWidget { + background-color: #444444; +} + +#GemCatalogHeaderWidget { + background-color: #1E252F; +} + +#GemCatalogFilterCategoryTitle { + font-size: 12px; + font-weight: 600; +} diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp index 6e9ad42017..6402121e4a 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp @@ -25,10 +25,12 @@ namespace O3DE::ProjectManager hLayout->setMargin(0); setLayout(hLayout); - setStyleSheet("background-color: #1E252F;"); + setObjectName("GemCatalogHeaderWidget"); + + hLayout->addSpacing(7); QLabel* titleLabel = new QLabel(tr("Gem Catalog")); - titleLabel->setStyleSheet("font-size: 21px;"); + titleLabel->setObjectName("GemCatalogTitle"); hLayout->addWidget(titleLabel); hLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding)); @@ -42,7 +44,7 @@ namespace O3DE::ProjectManager hLayout->addWidget(filterLineEdit); hLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding)); - hLayout->addSpacerItem(new QSpacerItem(220, 0, QSizePolicy::Fixed)); + hLayout->addSpacerItem(new QSpacerItem(140, 0, QSizePolicy::Fixed)); setFixedHeight(60); } diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp index 3ece7760cf..a6a4e95ff9 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp @@ -43,7 +43,6 @@ namespace O3DE::ProjectManager m_collapseButton->setFlat(true); m_collapseButton->setFocusPolicy(Qt::NoFocus); m_collapseButton->setFixedWidth(s_collapseButtonSize); - m_collapseButton->setStyleSheet("border: 0px; border-radius: 0px;"); connect(m_collapseButton, &QPushButton::clicked, this, [=]() { UpdateCollapseState(); @@ -52,7 +51,7 @@ namespace O3DE::ProjectManager // Category title QLabel* headerLabel = new QLabel(header); - headerLabel->setStyleSheet("font-size: 11pt;"); + headerLabel->setObjectName("GemCatalogFilterCategoryTitle"); collapseLayout->addWidget(headerLabel); vLayout->addLayout(collapseLayout); @@ -79,14 +78,14 @@ namespace O3DE::ProjectManager elementWidget->setLayout(elementLayout); QCheckBox* checkbox = new QCheckBox(elementNames[i]); - checkbox->setStyleSheet("font-size: 11pt;"); + checkbox->setStyleSheet("font-size: 12px;"); m_buttonGroup->addButton(checkbox); elementLayout->addWidget(checkbox); elementLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding)); QLabel* countLabel = new QLabel(QString::number(elementCounts[i])); - countLabel->setStyleSheet("font-size: 11pt; background-color: #333333; border-radius: 3px; color: #94D2FF;"); + countLabel->setStyleSheet("font-size: 12px; background-color: #333333; border-radius: 3px; color: #94D2FF;"); elementLayout->addWidget(countLabel); m_elementWidgets.push_back(elementWidget); @@ -110,6 +109,8 @@ namespace O3DE::ProjectManager } } + vLayout->addSpacing(5); + // Separating line QFrame* hLine = new QFrame(); hLine->setFrameShape(QFrame::HLine); @@ -181,6 +182,8 @@ namespace O3DE::ProjectManager : QScrollArea(parent) , m_filterProxyModel(filterProxyModel) { + setObjectName("GemCatalogFilterWidget"); + m_gemModel = m_filterProxyModel->GetSourceModel(); setWidgetResizable(true); @@ -195,7 +198,7 @@ namespace O3DE::ProjectManager mainWidget->setLayout(m_mainLayout); QLabel* filterByLabel = new QLabel("Filter by"); - filterByLabel->setStyleSheet("font-size: 15pt;"); + filterByLabel->setStyleSheet("font-size: 16px;"); m_mainLayout->addWidget(filterByLabel); AddGemOriginFilter(); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp index 6276ddc996..3ecc18231e 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp @@ -23,6 +23,7 @@ namespace O3DE::ProjectManager : QScrollArea(parent) , m_model(model) { + setObjectName("GemCatalogInspector"); setWidgetResizable(true); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); @@ -85,7 +86,7 @@ namespace O3DE::ProjectManager QLabel* GemInspector::CreateStyledLabel(QLayout* layout, int fontSize, const QString& colorCodeString) { QLabel* result = new QLabel(); - result->setStyleSheet(QString("font-size: %1pt; color: %2;").arg(QString::number(fontSize), colorCodeString)); + result->setStyleSheet(QString("font-size: %1px; color: %2;").arg(QString::number(fontSize), colorCodeString)); layout->addWidget(result); return result; } @@ -93,13 +94,13 @@ namespace O3DE::ProjectManager void GemInspector::InitMainWidget() { // Gem name, creator and summary - m_nameLabel = CreateStyledLabel(m_mainLayout, 17, s_headerColor); + m_nameLabel = CreateStyledLabel(m_mainLayout, 18, s_headerColor); m_creatorLabel = CreateStyledLabel(m_mainLayout, 12, s_creatorColor); m_mainLayout->addSpacing(5); // TODO: QLabel seems to have issues determining the right sizeHint() for our font with the given font size. // This results into squeezed elements in the layout in case the text is a little longer than a sentence. - m_summaryLabel = new QLabel();//CreateLabel(m_mainLayout, 12, s_textColor); + m_summaryLabel = CreateStyledLabel(m_mainLayout, 12, s_textColor); m_mainLayout->addWidget(m_summaryLabel); m_summaryLabel->setWordWrap(true); m_mainLayout->addSpacing(5); @@ -146,9 +147,9 @@ namespace O3DE::ProjectManager QLabel* additionalInfoLabel = CreateStyledLabel(m_mainLayout, 14, s_headerColor); additionalInfoLabel->setText("Additional Information"); - m_versionLabel = CreateStyledLabel(m_mainLayout, 11, s_textColor); - m_lastUpdatedLabel = CreateStyledLabel(m_mainLayout, 11, s_textColor); - m_binarySizeLabel = CreateStyledLabel(m_mainLayout, 11, s_textColor); + m_versionLabel = CreateStyledLabel(m_mainLayout, 12, s_textColor); + m_lastUpdatedLabel = CreateStyledLabel(m_mainLayout, 12, s_textColor); + m_binarySizeLabel = CreateStyledLabel(m_mainLayout, 12, s_textColor); } GemInspector::GemsSubWidget::GemsSubWidget(QWidget* parent) @@ -159,8 +160,8 @@ namespace O3DE::ProjectManager m_layout->setMargin(0); setLayout(m_layout); - m_titleLabel = GemInspector::CreateStyledLabel(m_layout, 15, s_headerColor); - m_textLabel = GemInspector::CreateStyledLabel(m_layout, 9, s_textColor); + m_titleLabel = GemInspector::CreateStyledLabel(m_layout, 16, s_headerColor); + m_textLabel = GemInspector::CreateStyledLabel(m_layout, 10, s_textColor); m_textLabel->setWordWrap(true); m_tagWidget = new TagContainerWidget(); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp index a40e5eb447..57200e3b36 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp @@ -49,7 +49,7 @@ namespace O3DE::ProjectManager painter->setRenderHint(QPainter::Antialiasing); QRect fullRect, itemRect, contentRect; - CalcRects(options, modelIndex, fullRect, itemRect, contentRect); + CalcRects(options, fullRect, itemRect, contentRect); QFont standardFont(options.font); standardFont.setPixelSize(s_fontSize); @@ -99,7 +99,7 @@ namespace O3DE::ProjectManager painter->drawText(gemCreatorRect, Qt::TextSingleLine, gemCreator); // Gem summary - const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_buttonWidth - s_itemMargins.right() * 4, contentRect.height()); + const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_buttonWidth - s_itemMargins.right() * 3, contentRect.height()); const QRect summaryRect = QRect(/*topLeft=*/QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), summarySize); painter->setFont(standardFont); @@ -134,12 +134,10 @@ namespace O3DE::ProjectManager return QStyledItemDelegate::editorEvent(event, model, option, modelIndex); } - void GemItemDelegate::CalcRects(const QStyleOptionViewItem& option, const QModelIndex& modelIndex, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const + void GemItemDelegate::CalcRects(const QStyleOptionViewItem& option, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const { - const bool isFirst = modelIndex.row() == 0; - outFullRect = QRect(option.rect); - outItemRect = QRect(outFullRect.adjusted(s_itemMargins.left(), isFirst ? s_itemMargins.top() * 2 : s_itemMargins.top(), -s_itemMargins.right(), -s_itemMargins.bottom())); + outItemRect = QRect(outFullRect.adjusted(s_itemMargins.left(), s_itemMargins.top(), -s_itemMargins.right(), -s_itemMargins.bottom())); outContentRect = QRect(outItemRect.adjusted(s_contentMargins.left(), s_contentMargins.top(), -s_contentMargins.right(), -s_contentMargins.bottom())); } @@ -194,12 +192,12 @@ namespace O3DE::ProjectManager painter->setBrush(m_buttonEnabledColor); painter->setPen(m_buttonEnabledColor); - circleCenter = buttonRect.center() + QPoint(buttonRect.width() / 2 - s_buttonBorderRadius, 1); + circleCenter = buttonRect.center() + QPoint(buttonRect.width() / 2 - s_buttonBorderRadius + 1, 1); buttonText = "Added"; } else { - circleCenter = buttonRect.center() + QPoint(-buttonRect.width() / 2 + s_buttonBorderRadius + 1, 1); + circleCenter = buttonRect.center() + QPoint(-buttonRect.width() / 2 + s_buttonBorderRadius, 1); buttonText = "Get"; } diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h index d43b5d15f6..48f173ec3f 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h @@ -45,25 +45,25 @@ namespace O3DE::ProjectManager const QColor m_buttonEnabledColor = QColor("#00B931"); // Item - inline constexpr static int s_height = 135; // Gem item total height - inline constexpr static qreal s_gemNameFontSize = 16.0; - inline constexpr static qreal s_fontSize = 15.0; - inline constexpr static int s_summaryStartX = 200; + inline constexpr static int s_height = 105; // Gem item total height + inline constexpr static qreal s_gemNameFontSize = 13.0; + inline constexpr static qreal s_fontSize = 12.0; + inline constexpr static int s_summaryStartX = 150; // Margin and borders - inline constexpr static QMargins s_itemMargins = QMargins(/*left=*/20, /*top=*/10, /*right=*/20, /*bottom=*/10); // Item border distances - inline constexpr static QMargins s_contentMargins = QMargins(/*left=*/15, /*top=*/12, /*right=*/12, /*bottom=*/12); // Distances of the elements within an item to the item borders + inline constexpr static QMargins s_itemMargins = QMargins(/*left=*/16, /*top=*/8, /*right=*/16, /*bottom=*/8); // Item border distances + inline constexpr static QMargins s_contentMargins = QMargins(/*left=*/20, /*top=*/12, /*right=*/15, /*bottom=*/12); // Distances of the elements within an item to the item borders inline constexpr static int s_borderWidth = 4; // Button - inline constexpr static int s_buttonWidth = 70; - inline constexpr static int s_buttonHeight = 24; - inline constexpr static int s_buttonBorderRadius = 12; - inline constexpr static int s_buttonCircleRadius = s_buttonBorderRadius - 3; - inline constexpr static qreal s_buttonFontSize = 12.0; + inline constexpr static int s_buttonWidth = 55; + inline constexpr static int s_buttonHeight = 18; + inline constexpr static int s_buttonBorderRadius = 9; + inline constexpr static int s_buttonCircleRadius = s_buttonBorderRadius - 2; + inline constexpr static qreal s_buttonFontSize = 10.0; private: - void CalcRects(const QStyleOptionViewItem& option, const QModelIndex& modelIndex, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const; + void CalcRects(const QStyleOptionViewItem& option, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const; QRect GetTextRect(QFont& font, const QString& text, qreal fontSize) const; QRect CalcButtonRect(const QRect& contentRect) const; void DrawPlatformIcons(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const; @@ -73,7 +73,7 @@ namespace O3DE::ProjectManager // Platform icons void AddPlatformIcon(GemInfo::Platform platform, const QString& iconPath); - inline constexpr static int s_platformIconSize = 16; + inline constexpr static int s_platformIconSize = 12; QHash m_platformIcons; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp index 128fb93345..bc287e3c61 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp @@ -35,7 +35,7 @@ namespace O3DE::ProjectManager topLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding)); QLabel* showCountLabel = new QLabel(); - showCountLabel->setStyleSheet("font-size: 11pt; font: italic;"); + showCountLabel->setStyleSheet("font-size: 12px; font: italic;"); topLayout->addWidget(showCountLabel); connect(proxyModel, &GemSortFilterProxyModel::OnInvalidated, this, [=] { @@ -61,16 +61,17 @@ namespace O3DE::ProjectManager QHBoxLayout* columnHeaderLayout = new QHBoxLayout(); columnHeaderLayout->setAlignment(Qt::AlignLeft); - columnHeaderLayout->addSpacing(31); + const int gemNameStartX = GemItemDelegate::s_itemMargins.left() + GemItemDelegate::s_contentMargins.left() - 3; + columnHeaderLayout->addSpacing(gemNameStartX); QLabel* gemNameLabel = new QLabel(tr("Gem Name")); - gemNameLabel->setStyleSheet("font-size: 11pt;"); + gemNameLabel->setStyleSheet("font-size: 12px;"); columnHeaderLayout->addWidget(gemNameLabel); - columnHeaderLayout->addSpacing(111); + columnHeaderLayout->addSpacing(77); QLabel* gemSummaryLabel = new QLabel(tr("Gem Summary")); - gemSummaryLabel->setStyleSheet("font-size: 11pt;"); + gemSummaryLabel->setStyleSheet("font-size: 12px;"); columnHeaderLayout->addWidget(gemSummaryLabel); vLayout->addLayout(columnHeaderLayout); diff --git a/Code/Tools/ProjectManager/Source/LinkWidget.cpp b/Code/Tools/ProjectManager/Source/LinkWidget.cpp index a6308f6c62..160d9cf7c7 100644 --- a/Code/Tools/ProjectManager/Source/LinkWidget.cpp +++ b/Code/Tools/ProjectManager/Source/LinkWidget.cpp @@ -37,7 +37,7 @@ namespace O3DE::ProjectManager void LinkLabel::enterEvent([[maybe_unused]] QEvent* event) { - setStyleSheet("font-size: 9pt; color: #94D2FF; text-decoration: underline;"); + setStyleSheet("font-size: 10px; color: #94D2FF; text-decoration: underline;"); } void LinkLabel::leaveEvent([[maybe_unused]] QEvent* event) @@ -52,6 +52,6 @@ namespace O3DE::ProjectManager void LinkLabel::SetDefaultStyle() { - setStyleSheet("font-size: 9pt; color: #94D2FF;"); + setStyleSheet("font-size: 10px; color: #94D2FF;"); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/TagWidget.cpp b/Code/Tools/ProjectManager/Source/TagWidget.cpp index 3e80944204..628b682b95 100644 --- a/Code/Tools/ProjectManager/Source/TagWidget.cpp +++ b/Code/Tools/ProjectManager/Source/TagWidget.cpp @@ -18,9 +18,9 @@ namespace O3DE::ProjectManager TagWidget::TagWidget(const QString& text, QWidget* parent) : QLabel(text, parent) { - setFixedHeight(35); + setFixedHeight(24); setMargin(5); - setStyleSheet("font-size: 12pt; background-color: #333333; border-radius: 4px;"); + setStyleSheet("font-size: 12px; background-color: #333333; border-radius: 3px;"); } TagContainerWidget::TagContainerWidget(QWidget* parent) @@ -35,7 +35,7 @@ namespace O3DE::ProjectManager void TagContainerWidget::Update(const QStringList& tags) { QWidget* parentWidget = qobject_cast(parent()); - int width = 250; + int width = 200; if (parentWidget) { width = parentWidget->width(); From c9f7cd03bb122190650094412d637336ec5a4569 Mon Sep 17 00:00:00 2001 From: Aaron Ruiz Mora Date: Fri, 28 May 2021 12:26:53 +0100 Subject: [PATCH 28/41] Limit convex and primitive methods of export physx asset to one material --- Gems/PhysX/Code/Source/Pipeline/MeshExporter.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Gems/PhysX/Code/Source/Pipeline/MeshExporter.cpp b/Gems/PhysX/Code/Source/Pipeline/MeshExporter.cpp index 3aeb3ad797..56042fbc91 100644 --- a/Gems/PhysX/Code/Source/Pipeline/MeshExporter.cpp +++ b/Gems/PhysX/Code/Source/Pipeline/MeshExporter.cpp @@ -794,6 +794,9 @@ namespace PhysX ); } + // Convex and primitive methods can only have 1 material + const bool limitToOneMaterial = pxMeshGroup.GetExportAsConvex() || pxMeshGroup.GetExportAsPrimitive(); + for (AZ::u32 faceIndex = 0; faceIndex < faceCount; ++faceIndex) { AZStd::string materialName = DefaultMaterialName; @@ -810,6 +813,14 @@ namespace PhysX } materialName = localFbxMaterialsList[materialId]; + + // Keep using the first material when it has to be limited to one. + if (limitToOneMaterial && + assetMaterialData.m_fbxMaterialNames.size() == 1 && + assetMaterialData.m_fbxMaterialNames[0] != materialName) + { + materialName = assetMaterialData.m_fbxMaterialNames[0]; + } } const AZ::SceneAPI::DataTypes::IMeshData::Face& face = nodeMesh->GetFaceInfo(faceIndex); From 36ceff84c9fd6ce9a4dacd4d2543f7ef7bcd4293 Mon Sep 17 00:00:00 2001 From: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> Date: Fri, 28 May 2021 14:37:17 +0100 Subject: [PATCH 29/41] Support mesh intersection for camera orbit (#982) * wip support for mesh intersection with intersector bus * WIP camera mesh intersection orbit logic * remove unneeded template argument * add bus connect/disconnect * fix intersection logic * small updates, additional comments, some tidy-up * update formatting options slightly * use aznumeric_cast * temp workaround for negative distances with RayIntersection --- .clang-format | 2 +- .../Render/GeometryIntersectionBus.h | 7 +- .../AzFramework/Viewport/CameraInput.cpp | 60 +++++++---- .../AzFramework/Viewport/CameraInput.h | 26 +++-- Code/Sandbox/Editor/EditorViewportWidget.cpp | 101 +++++++++++------- .../Code/Source/Mesh/EditorMeshComponent.h | 3 +- .../Code/Source/Mesh/MeshComponent.h | 3 +- .../Source/Mesh/MeshComponentController.cpp | 73 ++++++++++--- .../Source/Mesh/MeshComponentController.h | 16 +-- 9 files changed, 191 insertions(+), 100 deletions(-) diff --git a/.clang-format b/.clang-format index 565f28130e..04e0284f97 100644 --- a/.clang-format +++ b/.clang-format @@ -46,7 +46,7 @@ SortIncludes: true SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: false SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: true +SpaceBeforeCpp11BracedList: false SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements diff --git a/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h b/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h index ba1d2d1e06..749f457286 100644 --- a/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h +++ b/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h @@ -12,6 +12,7 @@ #pragma once #include +#include #include namespace AzFramework @@ -35,12 +36,12 @@ namespace AzFramework AzFramework::EntityContextId m_contextId; }; - //! Interface for intersection requests, implement this interface for making your component - //! render geometry intersectable. + //! Interface for intersection requests. + //! Implement this interface to make your component 'intersectable'. class IntersectionRequests : public AZ::EBusTraits { - //! Policy for notifying the Intersector bus of entities connected/disconnected to this ebus + //! Policy for notifying the Intersector bus of entities connected/disconnected to this EBus //! so it updates the internal data of the entities template struct IntersectionRequestsConnectionPolicy diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index e4833ccb3c..d5f02c957c 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -144,7 +144,7 @@ namespace AzFramework z = AZStd::atan2(-orientation.GetElement(1, 2), orientation.GetElement(1, 1)); } - return {x, y, z}; + return { x, y, z }; } void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform) @@ -179,7 +179,7 @@ namespace AzFramework { const auto nextCamera = m_cameras.StepCamera(targetCamera, m_motionDelta, m_scrollDelta, deltaTime); - m_motionDelta = ScreenVector{0, 0}; + m_motionDelta = ScreenVector{ 0, 0 }; m_scrollDelta = 0.0f; return nextCamera; @@ -213,7 +213,10 @@ namespace AzFramework auto& cameraInput = m_idleCameraInputs[i]; const bool canBegin = cameraInput->Beginning() && AZStd::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(), - [](const auto& input) { return !input->Exclusive(); }) && + [](const auto& input) + { + return !input->Exclusive(); + }) && (!cameraInput->Exclusive() || (cameraInput->Exclusive() && m_activeCameraInputs.empty())); if (canBegin) @@ -231,7 +234,8 @@ namespace AzFramework const Camera nextCamera = AZStd::accumulate( AZStd::begin(m_activeCameraInputs), AZStd::end(m_activeCameraInputs), targetCamera, - [cursorDelta, scrollDelta, deltaTime](Camera acc, auto& camera) { + [cursorDelta, scrollDelta, deltaTime](Camera acc, auto& camera) + { acc = camera->StepCamera(acc, cursorDelta, scrollDelta, deltaTime); return acc; }); @@ -284,7 +288,8 @@ namespace AzFramework bool RotateCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta) { - const ClickDetector::ClickEvent clickEvent = [&event, this] { + const ClickDetector::ClickEvent clickEvent = [&event, this] + { if (const auto& input = AZStd::get_if(&event)) { if (input->m_channelId == m_rotateChannelId) @@ -330,7 +335,10 @@ namespace AzFramework nextCamera.m_pitch -= float(cursorDelta.m_y) * ed_cameraSystemRotateSpeed; nextCamera.m_yaw -= float(cursorDelta.m_x) * ed_cameraSystemRotateSpeed; - const auto clampRotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; + const auto clampRotation = [](const float angle) + { + return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); + }; nextCamera.m_yaw = clampRotation(nextCamera.m_yaw); // clamp pitch to be +-90 degrees @@ -377,9 +385,10 @@ namespace AzFramework const auto deltaPanX = float(cursorDelta.m_x) * panAxes.m_horizontalAxis * ed_cameraSystemPanSpeed; const auto deltaPanY = float(cursorDelta.m_y) * panAxes.m_verticalAxis * ed_cameraSystemPanSpeed; - const auto inv = [](const bool invert) { - constexpr float Dir[] = {1.0f, -1.0f}; - return Dir[static_cast(invert)]; + const auto inv = [](const bool invert) + { + constexpr float Dir[] = { 1.0f, -1.0f }; + return Dir[aznumeric_cast(invert)]; }; nextCamera.m_lookAt += deltaPanX * inv(ed_cameraSystemPanInvertX); @@ -475,7 +484,8 @@ namespace AzFramework const auto axisY = translationBasis.GetBasisY(); const auto axisZ = translationBasis.GetBasisZ(); - const float speed = [boost = m_boost]() { + const float speed = [boost = m_boost]() + { return ed_cameraSystemTranslateSpeed * (boost ? ed_cameraSystemBoostMultiplier : 1.0f); }(); @@ -555,10 +565,12 @@ namespace AzFramework if (Beginning()) { - const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn] { + const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn] + { if (lookAtFn) { - if (const auto lookAt = lookAtFn()) + // pass through the camera's position and look vector for use in the lookAt function + if (const auto lookAt = lookAtFn(targetCamera.Translation(), targetCamera.Rotation().GetBasisY())) { auto transform = AZ::Transform::CreateLookAt(targetCamera.m_lookAt, *lookAt); nextCamera.m_lookDist = -lookAt->GetDistance(targetCamera.m_lookAt); @@ -692,14 +704,20 @@ namespace AzFramework Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const float deltaTime) { - const auto clamp_rotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; + const auto clamp_rotation = [](const float angle) + { + return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); + }; // keep yaw in 0 - 360 range float targetYaw = clamp_rotation(targetCamera.m_yaw); const float currentYaw = clamp_rotation(currentCamera.m_yaw); // return the sign of the float input (-1, 0, 1) - const auto sign = [](const float value) { return aznumeric_cast((0.0f < value) - (value < 0.0f)); }; + const auto sign = [](const float value) + { + return aznumeric_cast((0.0f < value) - (value < 0.0f)); + }; // ensure smooth transition when moving across 0 - 360 boundary const float yawDelta = targetYaw - currentYaw; @@ -727,26 +745,28 @@ namespace AzFramework const auto& inputChannelId = inputChannel.GetInputChannelId(); const auto& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId(); - const bool wasMouseButton = - AZStd::any_of(InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(), [inputChannelId](const auto& button) { + const bool wasMouseButton = AZStd::any_of( + InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(), + [inputChannelId](const auto& button) + { return button == inputChannelId; }); if (inputChannelId == InputDeviceMouse::Movement::X) { - return HorizontalMotionEvent{(int)inputChannel.GetValue()}; + return HorizontalMotionEvent{ aznumeric_cast(inputChannel.GetValue()) }; } else if (inputChannelId == InputDeviceMouse::Movement::Y) { - return VerticalMotionEvent{(int)inputChannel.GetValue()}; + return VerticalMotionEvent{ aznumeric_cast(inputChannel.GetValue()) }; } else if (inputChannelId == InputDeviceMouse::Movement::Z) { - return ScrollEvent{inputChannel.GetValue()}; + return ScrollEvent{ inputChannel.GetValue() }; } else if (wasMouseButton || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId)) { - return DiscreteInputEvent{inputChannelId, inputChannel.GetState()}; + return DiscreteInputEvent{ inputChannelId, inputChannel.GetState() }; } return AZStd::monostate{}; diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h index ec70fc00de..a02f796899 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h @@ -34,9 +34,9 @@ namespace AzFramework AZ::Vector3 m_lookAt = AZ::Vector3::CreateZero(); //!< Position of camera when m_lookDist is zero, //!< or position of m_lookAt when m_lookDist is greater //!< than zero. - float m_yaw{0.0}; - float m_pitch{0.0}; - float m_lookDist{0.0}; //!< Zero gives first person free look, otherwise orbit about m_lookAt + float m_yaw{ 0.0 }; + float m_pitch{ 0.0 }; + float m_lookDist{ 0.0 }; //!< Zero gives first person free look, otherwise orbit about m_lookAt //! View camera transform (v in MVP). AZ::Transform View() const; @@ -195,7 +195,11 @@ namespace AzFramework inline bool Cameras::Exclusive() const { return AZStd::any_of( - m_activeCameraInputs.begin(), m_activeCameraInputs.end(), [](const auto& cameraInput) { return cameraInput->Exclusive(); }); + m_activeCameraInputs.begin(), m_activeCameraInputs.end(), + [](const auto& cameraInput) + { + return cameraInput->Exclusive(); + }); } //! Responsible for updating a series of cameras given various inputs. @@ -209,7 +213,7 @@ namespace AzFramework private: ScreenVector m_motionDelta; //!< The delta used for look/orbit/pan (rotation + translation) - two dimensional. - float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional. + float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional. }; class RotateCameraInput : public CameraInput @@ -237,7 +241,7 @@ namespace AzFramework inline PanAxes LookPan(const Camera& camera) { const AZ::Matrix3x3 orientation = camera.Rotation(); - return {orientation.GetBasisX(), orientation.GetBasisZ()}; + return { orientation.GetBasisX(), orientation.GetBasisZ() }; } inline PanAxes OrbitPan(const Camera& camera) @@ -245,12 +249,13 @@ namespace AzFramework const AZ::Matrix3x3 orientation = camera.Rotation(); const auto basisX = orientation.GetBasisX(); - const auto basisY = [&orientation] { + const auto basisY = [&orientation] + { const auto forward = orientation.GetBasisY(); return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized(); }(); - return {basisX, basisY}; + return { basisX, basisY }; } class PanCameraInput : public CameraInput @@ -285,7 +290,8 @@ namespace AzFramework const AZ::Matrix3x3 orientation = camera.Rotation(); const auto basisX = orientation.GetBasisX(); - const auto basisY = [&orientation] { + const auto basisY = [&orientation] + { const auto forward = orientation.GetBasisY(); return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized(); }(); @@ -398,7 +404,7 @@ namespace AzFramework class OrbitCameraInput : public CameraInput { public: - using LookAtFn = AZStd::function()>; + using LookAtFn = AZStd::function(const AZ::Vector3& position, const AZ::Vector3& direction)>; // CameraInput overrides ... bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index ecd11da817..989d6e407d 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -1221,50 +1221,73 @@ void EditorViewportWidget::SetViewportId(int id) AzFramework::ReloadCameraKeyBindings(); auto controller = AZStd::make_shared(); - controller->SetCameraListBuilderCallback([](AzFramework::Cameras& cameras) - { - auto firstPersonRotateCamera = AZStd::make_shared(AzFramework::CameraFreeLookButton); - auto firstPersonPanCamera = - AZStd::make_shared(AzFramework::CameraFreePanButton, AzFramework::LookPan); - auto firstPersonTranslateCamera = AZStd::make_shared(AzFramework::LookTranslation); - auto firstPersonWheelCamera = AZStd::make_shared(); + controller->SetCameraListBuilderCallback( + [](AzFramework::Cameras& cameras) + { + auto firstPersonRotateCamera = AZStd::make_shared(AzFramework::CameraFreeLookButton); + auto firstPersonPanCamera = + AZStd::make_shared(AzFramework::CameraFreePanButton, AzFramework::LookPan); + auto firstPersonTranslateCamera = AZStd::make_shared(AzFramework::LookTranslation); + auto firstPersonWheelCamera = AZStd::make_shared(); - auto orbitCamera = AZStd::make_shared(); - orbitCamera->SetLookAtFn([]() -> AZStd::optional { - AZStd::optional manipulatorTransform; - AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult( - manipulatorTransform, AzToolsFramework::GetEntityContextId(), - &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform); + auto orbitCamera = AZStd::make_shared(); + orbitCamera->SetLookAtFn( + [](const AZ::Vector3& position, const AZ::Vector3& direction) -> AZStd::optional + { + AZStd::optional manipulatorTransform; + AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult( + manipulatorTransform, AzToolsFramework::GetEntityContextId(), + &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform); - if (manipulatorTransform) - { - return manipulatorTransform->GetTranslation(); - } + // initially attempt to use manipulator transform if one exists (there is a selection) + if (manipulatorTransform) + { + return manipulatorTransform->GetTranslation(); + } - return {}; + const float RayDistance = 1000.0f; + AzFramework::RenderGeometry::RayRequest ray; + ray.m_startWorldPosition = position; + ray.m_endWorldPosition = position + direction * RayDistance; + ray.m_onlyVisible = true; + + AzFramework::RenderGeometry::RayResult renderGeometryIntersectionResult; + AzFramework::RenderGeometry::IntersectorBus::EventResult( + renderGeometryIntersectionResult, AzToolsFramework::GetEntityContextId(), + &AzFramework::RenderGeometry::IntersectorInterface::RayIntersect, ray); + + // attempt a ray intersection with any visible mesh and return the intersection position if successful + if (renderGeometryIntersectionResult) + { + return renderGeometryIntersectionResult.m_worldPosition; + } + + // if there is no selection or no intersection, fallback to default camera orbit behavior (ground plane + // intersection) + return {}; + }); + + auto orbitRotateCamera = AZStd::make_shared(AzFramework::CameraOrbitLookButton); + auto orbitTranslateCamera = AZStd::make_shared(AzFramework::OrbitTranslation); + auto orbitDollyWheelCamera = AZStd::make_shared(); + auto orbitDollyMoveCamera = + AZStd::make_shared(AzFramework::CameraOrbitDollyButton); + auto orbitPanCamera = + AZStd::make_shared(AzFramework::CameraOrbitPanButton, AzFramework::OrbitPan); + + orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera); + orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera); + orbitCamera->m_orbitCameras.AddCamera(orbitDollyWheelCamera); + orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera); + orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera); + + cameras.AddCamera(firstPersonRotateCamera); + cameras.AddCamera(firstPersonPanCamera); + cameras.AddCamera(firstPersonTranslateCamera); + cameras.AddCamera(firstPersonWheelCamera); + cameras.AddCamera(orbitCamera); }); - auto orbitRotateCamera = AZStd::make_shared(AzFramework::CameraOrbitLookButton); - auto orbitTranslateCamera = AZStd::make_shared(AzFramework::OrbitTranslation); - auto orbitDollyWheelCamera = AZStd::make_shared(); - auto orbitDollyMoveCamera = - AZStd::make_shared(AzFramework::CameraOrbitDollyButton); - auto orbitPanCamera = - AZStd::make_shared(AzFramework::CameraOrbitPanButton, AzFramework::OrbitPan); - - orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera); - orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera); - orbitCamera->m_orbitCameras.AddCamera(orbitDollyWheelCamera); - orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera); - orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera); - - cameras.AddCamera(firstPersonRotateCamera); - cameras.AddCamera(firstPersonPanCamera); - cameras.AddCamera(firstPersonTranslateCamera); - cameras.AddCamera(firstPersonWheelCamera); - cameras.AddCamera(orbitCamera); - }); - m_renderViewport->GetControllerList()->Add(controller); } else diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h index 1acaa6fdf8..41ea80f8d1 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h @@ -35,14 +35,13 @@ namespace AZ , private MeshComponentNotificationBus::Handler { public: - using BaseClass = EditorRenderComponentAdapter; AZ_EDITOR_COMPONENT(AZ::Render::EditorMeshComponent, EditorMeshComponentTypeId, BaseClass); static void Reflect(AZ::ReflectContext* context); EditorMeshComponent() = default; - EditorMeshComponent(const MeshComponentConfig& config); + explicit EditorMeshComponent(const MeshComponentConfig& config); // AZ::Component overrides ... void Activate() override; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponent.h index a57780c384..fe7f45d7d1 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponent.h @@ -25,12 +25,11 @@ namespace AZ : public AzFramework::Components::ComponentAdapter { public: - using BaseClass = AzFramework::Components::ComponentAdapter; AZ_COMPONENT(AZ::Render::MeshComponent, MeshComponentTypeId, BaseClass); MeshComponent() = default; - MeshComponent(const MeshComponentConfig& config); + explicit MeshComponent(const MeshComponentConfig& config); static void Reflect(AZ::ReflectContext* context); }; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index a4a91cf708..c089dd01f9 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -177,28 +177,33 @@ namespace AZ FixUpModelAsset(m_configuration.m_modelAsset); } - void MeshComponentController::Activate(AZ::EntityId entityId) + void MeshComponentController::Activate(const AZ::EntityComponentIdPair& entityComponentIdPair) { FixUpModelAsset(m_configuration.m_modelAsset); - m_entityId = entityId; + const AZ::EntityId entityId = entityComponentIdPair.GetEntityId(); + m_entityComponentIdPair = entityComponentIdPair; - m_transformInterface = TransformBus::FindFirstHandler(m_entityId); + m_transformInterface = TransformBus::FindFirstHandler(entityId); AZ_Warning("MeshComponentController", m_transformInterface, "Unable to attach to a TransformBus handler. This mesh will always be rendered at the origin."); - m_meshFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity(m_entityId); + m_meshFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity(entityId); AZ_Error("MeshComponentController", m_meshFeatureProcessor, "Unable to find a MeshFeatureProcessorInterface on the entityId."); m_cachedNonUniformScale = AZ::Vector3::CreateOne(); - AZ::NonUniformScaleRequestBus::EventResult(m_cachedNonUniformScale, m_entityId, &AZ::NonUniformScaleRequests::GetScale); - AZ::NonUniformScaleRequestBus::Event(m_entityId, &AZ::NonUniformScaleRequests::RegisterScaleChangedEvent, + AZ::NonUniformScaleRequestBus::EventResult(m_cachedNonUniformScale, entityId, &AZ::NonUniformScaleRequests::GetScale); + AZ::NonUniformScaleRequestBus::Event(entityId, &AZ::NonUniformScaleRequests::RegisterScaleChangedEvent, m_nonUniformScaleChangedHandler); - MeshComponentRequestBus::Handler::BusConnect(m_entityId); - TransformNotificationBus::Handler::BusConnect(m_entityId); - MaterialReceiverRequestBus::Handler::BusConnect(m_entityId); - MaterialComponentNotificationBus::Handler::BusConnect(m_entityId); - AzFramework::BoundsRequestBus::Handler::BusConnect(m_entityId); + MeshComponentRequestBus::Handler::BusConnect(entityId); + TransformNotificationBus::Handler::BusConnect(entityId); + MaterialReceiverRequestBus::Handler::BusConnect(entityId); + MaterialComponentNotificationBus::Handler::BusConnect(entityId); + AzFramework::BoundsRequestBus::Handler::BusConnect(entityId); + AzFramework::EntityContextId contextId; + AzFramework::EntityIdContextQueryBus::EventResult( + contextId, entityId, &AzFramework::EntityIdContextQueries::GetOwningContextId); + AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusConnect({entityId, contextId}); //Buses must be connected before RegisterModel in case requests are made as a result of HandleModelChange RegisterModel(); @@ -209,6 +214,7 @@ namespace AZ // Buses must be disconnected after unregistering the model, otherwise they can't deliver the events during the process. UnregisterModel(); + AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusDisconnect(); AzFramework::BoundsRequestBus::Handler::BusDisconnect(); MeshComponentRequestBus::Handler::BusDisconnect(); TransformNotificationBus::Handler::BusDisconnect(); @@ -219,7 +225,7 @@ namespace AZ m_meshFeatureProcessor = nullptr; m_transformInterface = nullptr; - m_entityId = AZ::EntityId(AZ::EntityId::InvalidEntityId); + m_entityComponentIdPair = AZ::EntityComponentIdPair(AZ::EntityId(), AZ::InvalidComponentId); m_configuration.m_modelAsset.Release(); } @@ -293,10 +299,11 @@ namespace AZ Data::Asset modelAsset = m_meshFeatureProcessor->GetModelAsset(m_meshHandle); if (model && modelAsset) { + const AZ::EntityId entityId = m_entityComponentIdPair.GetEntityId(); m_configuration.m_modelAsset = modelAsset; - MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelReady, m_configuration.m_modelAsset, model); - MaterialReceiverNotificationBus::Event(m_entityId, &MaterialReceiverNotificationBus::Events::OnMaterialAssignmentsChanged); - AZ::Interface::Get()->RefreshEntityLocalBoundsUnion(m_entityId); + MeshComponentNotificationBus::Event(entityId, &MeshComponentNotificationBus::Events::OnModelReady, m_configuration.m_modelAsset, model); + MaterialReceiverNotificationBus::Event(entityId, &MaterialReceiverNotificationBus::Events::OnMaterialAssignmentsChanged); + AZ::Interface::Get()->RefreshEntityLocalBoundsUnion(entityId); } } @@ -304,8 +311,10 @@ namespace AZ { if (m_meshFeatureProcessor && m_configuration.m_modelAsset.GetId().IsValid()) { + const AZ::EntityId entityId = m_entityComponentIdPair.GetEntityId(); + MaterialAssignmentMap materials; - MaterialComponentRequestBus::EventResult(materials, m_entityId, &MaterialComponentRequests::GetMaterialOverrides); + MaterialComponentRequestBus::EventResult(materials, entityId, &MaterialComponentRequests::GetMaterialOverrides); m_meshFeatureProcessor->ReleaseMesh(m_meshHandle); m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials, @@ -330,7 +339,8 @@ namespace AZ { if (m_meshFeatureProcessor && m_meshHandle.IsValid()) { - MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelPreDestroy); + MeshComponentNotificationBus::Event( + m_entityComponentIdPair.GetEntityId(), &MeshComponentNotificationBus::Events::OnModelPreDestroy); m_meshFeatureProcessor->ReleaseMesh(m_meshHandle); } } @@ -462,5 +472,34 @@ namespace AZ return Aabb::CreateNull(); } } + + AzFramework::RenderGeometry::RayResult MeshComponentController::RenderGeometryIntersect( + const AzFramework::RenderGeometry::RayRequest& ray) + { + AzFramework::RenderGeometry::RayResult result; + if (const Data::Instance model = GetModel()) + { + float t; + AZ::Vector3 normal; + if (model->RayIntersection( + m_transformInterface->GetWorldTM(), m_cachedNonUniformScale, ray.m_startWorldPosition, + ray.m_endWorldPosition - ray.m_startWorldPosition, t, normal)) + { + // note: this is a temporary workaround to handle cases where model->RayIntersection + // returns negative distances, follow-up ATOM-15673 + const auto absT = AZStd::abs(t); + + // fill in ray result structure after successful intersection + const auto intersectionLine = (ray.m_endWorldPosition - ray.m_startWorldPosition); + result.m_uv = AZ::Vector2::CreateZero(); + result.m_worldPosition = ray.m_startWorldPosition + intersectionLine * absT; + result.m_worldNormal = normal; + result.m_distance = intersectionLine.GetLength() * absT; + result.m_entityAndComponent = m_entityComponentIdPair; + } + } + + return result; + } } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index 0cda34ea42..4d63e5e88d 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -13,11 +13,13 @@ #pragma once #include +#include #include #include #include +#include #include #include @@ -32,9 +34,7 @@ namespace AZ { namespace Render { - /** - * A configuration structure for the MeshComponentController - */ + //! A configuration structure for the MeshComponentController class MeshComponentConfig final : public AZ::ComponentConfig { @@ -57,6 +57,7 @@ namespace AZ class MeshComponentController final : private MeshComponentRequestBus::Handler , public AzFramework::BoundsRequestBus::Handler + , public AzFramework::RenderGeometry::IntersectionRequestBus::Handler , private TransformNotificationBus::Handler , private MaterialReceiverRequestBus::Handler , private MaterialComponentNotificationBus::Handler @@ -77,7 +78,7 @@ namespace AZ MeshComponentController() = default; MeshComponentController(const MeshComponentConfig& config); - void Activate(AZ::EntityId entityId); + void Activate(const AZ::EntityComponentIdPair& entityComponentIdPair); void Deactivate(); void SetConfiguration(const MeshComponentConfig& config); const MeshComponentConfig& GetConfiguration() const; @@ -103,10 +104,13 @@ namespace AZ void SetVisibility(bool visible) override; bool GetVisibility() const override; - // BoundsRequestBus and MeshComponentRequestBus ... + // BoundsRequestBus and MeshComponentRequestBus overrides ... AZ::Aabb GetWorldBounds() override; AZ::Aabb GetLocalBounds() override; + // IntersectionRequestBus overrides ... + AzFramework::RenderGeometry::RayResult RenderGeometryIntersect(const AzFramework::RenderGeometry::RayRequest& ray) override; + // TransformNotificationBus::Handler overrides ... void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; @@ -134,7 +138,7 @@ namespace AZ Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr; Render::MeshFeatureProcessorInterface::MeshHandle m_meshHandle; TransformInterface* m_transformInterface = nullptr; - AZ::EntityId m_entityId; + AZ::EntityComponentIdPair m_entityComponentIdPair; bool m_isVisible = true; MeshComponentConfig m_configuration; AZ::Vector3 m_cachedNonUniformScale = AZ::Vector3::CreateOne(); From 42b3e3817a7a15cc6ff1592afb6a78a12bb56eca Mon Sep 17 00:00:00 2001 From: pereslav Date: Fri, 28 May 2021 15:50:02 +0100 Subject: [PATCH 30/41] SPEC-7012 Added rewind-aware scene query utilities. Added frame ID to SimulatedBody --- .../Physics/Common/PhysicsSimulatedBody.h | 18 +++ .../Include/Multiplayer/MultiplayerTypes.h | 3 +- .../Multiplayer/Physics/PhysicsUtils.h | 37 +++++++ .../Code/Source/Physics/PhysicsUtils.cpp | 104 ++++++++++++++++++ Gems/Multiplayer/Code/multiplayer_files.cmake | 2 + 5 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 Gems/Multiplayer/Code/Include/Multiplayer/Physics/PhysicsUtils.h create mode 100644 Gems/Multiplayer/Code/Source/Physics/PhysicsUtils.cpp diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSimulatedBody.h b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSimulatedBody.h index ed8a68dc24..9d45a17edc 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSimulatedBody.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSimulatedBody.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,22 @@ namespace AzPhysics return m_customUserData; } + //! Helper functions for setting frame ID. + //! @param frameId Optionally set frame ID for the systems moving the actors back in time. + void SetFrameId(uint32_t frameId) + { + m_frameId = frameId; + } + + //! Helper functions for getting the set frame ID. + //! @return Will return the frame ID. + uint32_t GetFrameId() const + { + return m_frameId; + } + + static constexpr uint32_t UndefinedFrameId = AZStd::numeric_limits::max(); + //! Perform a ray cast on this Simulated Body. //! @param request The request to make. //! @return Returns the closest hit, if any, against this simulated body. @@ -126,6 +143,7 @@ namespace AzPhysics SimulatedBodyEvents::OnTriggerExit m_triggerExitEvent; void* m_customUserData = nullptr; + uint32_t m_frameId = UndefinedFrameId; // helpers for reflecting to behavior context SimulatedBodyEvents::OnCollisionBegin* GetOnCollisionBeginEvent(); diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerTypes.h b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerTypes.h index 16cc4146dd..85c7e85c0a 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerTypes.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/MultiplayerTypes.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,7 @@ namespace Multiplayer //! This is a strong typedef for representing the number of application frames since application start. AZ_TYPE_SAFE_INTEGRAL(HostFrameId, uint32_t); - static constexpr HostFrameId InvalidHostFrameId = HostFrameId{ 0xFFFFFFFF }; + static constexpr HostFrameId InvalidHostFrameId = HostFrameId{ AzPhysics::SimulatedBody::UndefinedFrameId }; using LongNetworkString = AZ::CVarFixedString; using ReliabilityType = AzNetworking::ReliabilityType; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Physics/PhysicsUtils.h b/Gems/Multiplayer/Code/Include/Multiplayer/Physics/PhysicsUtils.h new file mode 100644 index 0000000000..4013e20a1e --- /dev/null +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Physics/PhysicsUtils.h @@ -0,0 +1,37 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#pragma once + +#include + +namespace Multiplayer +{ + namespace Physics + { + //! Performs rewind-aware ray cast in the default physics world. + //! @param request The ray cast request to make. + //! @return Returns a structure that contains a list of Hits. + AzPhysics::SceneQueryHits RayCast(const AzPhysics::RayCastRequest& request); + + //! Performs rewind-aware shape cast in the default physics world. + //! @param request The shape cast request to make. + //! @return Returns a structure that contains a list of Hits. + AzPhysics::SceneQueryHits ShapeCast(const AzPhysics::ShapeCastRequest& request); + + //! Performs rewind-aware overlap in the default physics world. + //! @param request The overlap request to make. + //! @return Returns a structure that contains a list of Hits. + AzPhysics::SceneQueryHits Overlap(const AzPhysics::OverlapRequest& request); + + } // namespace Physics +} // namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Source/Physics/PhysicsUtils.cpp b/Gems/Multiplayer/Code/Source/Physics/PhysicsUtils.cpp new file mode 100644 index 0000000000..6341f5b060 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Physics/PhysicsUtils.cpp @@ -0,0 +1,104 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include + +#include +#include +#include +#include + +namespace +{ + template + AzPhysics::SceneQueryHits SceneQueryInternal(const RequestT& request) + { + auto* sceneInterface = AZ::Interface::Get(); + if (!sceneInterface) + { + return {}; + } + + AzPhysics::SceneHandle sceneHandle = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName); + if (sceneHandle == AzPhysics::InvalidSceneHandle) + { + return {}; + } + + Multiplayer::INetworkTime* currentNetTime = Multiplayer::GetNetworkTime(); + + if(!currentNetTime->IsTimeRewound()) + { + // If the time is not rewound, we simply execute the scene query as is. + AzPhysics::SceneQueryHits result = sceneInterface->QueryScene(sceneHandle, &request); + return result; + } + + // If the time is rewound, we want to query against rigid bodies present at the same frame ID: the same as the current rewound time is. + RequestT netSceneQueryRequest = request; + netSceneQueryRequest.m_filterCallback = [&request, currentFrameId = (uint32_t)currentNetTime->GetHostFrameId()]( + const AzPhysics::SimulatedBody* body, const ::Physics::Shape* shape) + { + if (body->GetFrameId() == AzPhysics::SimulatedBody::UndefinedFrameId || body->GetFrameId() == currentFrameId) + { + if (request.m_filterCallback) + { + return request.m_filterCallback(body, shape); + } + + // Overlap filter callbacks return true/false rather than Touch/Block/None + if constexpr (AZStd::is_same_v) + { + return true; + } + else + { + return AzPhysics::SceneQuery::QueryHitType::Touch; + } + } + + if constexpr (AZStd::is_same_v) + { + return false; + } + else + { + return AzPhysics::SceneQuery::QueryHitType::None; + } + }; + + // Execute the scene query modified for the time rewind. + AzPhysics::SceneQueryHits result = sceneInterface->QueryScene(sceneHandle, &netSceneQueryRequest); + return result; + } +} + +namespace Multiplayer +{ + namespace Physics + { + AzPhysics::SceneQueryHits RayCast(const AzPhysics::RayCastRequest& request) + { + return SceneQueryInternal(request); + } + + AzPhysics::SceneQueryHits ShapeCast(const AzPhysics::ShapeCastRequest& request) + { + return SceneQueryInternal(request); + } + + AzPhysics::SceneQueryHits Overlap(const AzPhysics::OverlapRequest& request) + { + return SceneQueryInternal(request); + } + } // namespace Physics +} // namespace Multiplayer diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index eb856a48db..28f32e02cc 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -35,6 +35,7 @@ set(FILES Include/Multiplayer/NetworkTime/INetworkTime.h Include/Multiplayer/NetworkTime/RewindableObject.h Include/Multiplayer/NetworkTime/RewindableObject.inl + Include/Multiplayer/Physics/PhysicsUtils.h Include/Multiplayer/ReplicationWindows/IReplicationWindow.h Source/Multiplayer_precompiled.cpp Source/Multiplayer_precompiled.h @@ -103,6 +104,7 @@ set(FILES Source/Pipeline/NetBindMarkerComponent.h Source/Pipeline/NetworkSpawnableHolderComponent.cpp Source/Pipeline/NetworkSpawnableHolderComponent.h + Source/Physics/PhysicsUtils.cpp Source/ReplicationWindows/NullReplicationWindow.cpp Source/ReplicationWindows/NullReplicationWindow.h Source/ReplicationWindows/ServerToClientReplicationWindow.cpp From 96905a26d718b8efdeb6228af4c0ac7599f5b931 Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Fri, 28 May 2021 09:57:17 -0500 Subject: [PATCH 31/41] Add support for AP-compliant relative paths (#998) The method "PrefabLoader::GetRelativePathToProject" has been changed to "PrefabLoader::GenerateRelativePath", and reworked to get a correct relative path. GetFullPath has also been modified to get correct relative paths too. This requires an Asset Processor connection - if one isn't available (like during unit tests), the methods have fallback logic to produce project-relative paths. With this change, SliceConverter can't use SaveTemplate() to save the file any more, because GetFullPath now expects to find an existing path, which doesn't work for not-yet-created files. Instead, it now has to use the same technique as the Editor and call SaveTemplateToString then save the string out as a file. --- .../PrefabEditorEntityOwnershipService.cpp | 29 +++--- .../Prefab/Instance/InstanceSerializer.cpp | 2 +- .../AzToolsFramework/Prefab/PrefabLoader.cpp | 95 +++++++++++++++++-- .../AzToolsFramework/Prefab/PrefabLoader.h | 8 +- .../Prefab/PrefabLoaderInterface.h | 8 +- .../Prefab/PrefabPublicHandler.cpp | 2 +- .../Prefab/PrefabSystemComponent.cpp | 2 +- .../UI/Prefab/PrefabIntegrationManager.cpp | 3 +- .../SerializeContextTools/SliceConverter.cpp | 28 ++++-- .../SerializeContextTools/SliceConverter.h | 2 +- 10 files changed, 143 insertions(+), 36 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index 439789f11b..7fd11ff9bf 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -57,7 +57,6 @@ namespace AzToolsFramework "Couldn't get prefab loader interface, it's a requirement for PrefabEntityOwnership system to work"); m_rootInstance = AZStd::unique_ptr(m_prefabSystemComponent->CreatePrefab({}, {}, "NewLevel.prefab")); - m_sliceOwnershipService.BusConnect(m_entityContextId); m_sliceOwnershipService.m_shouldAssertForLegacySlicesUsage = m_shouldAssertForLegacySlicesUsage; m_editorSliceOwnershipService.BusConnect(); @@ -91,14 +90,17 @@ namespace AzToolsFramework void PrefabEditorEntityOwnershipService::Reset() { - Prefab::TemplateId templateId = m_rootInstance->GetTemplateId(); - if (templateId != Prefab::InvalidTemplateId) + if (m_rootInstance) { - m_rootInstance->SetTemplateId(Prefab::InvalidTemplateId); - m_prefabSystemComponent->RemoveTemplate(templateId); + Prefab::TemplateId templateId = m_rootInstance->GetTemplateId(); + if (templateId != Prefab::InvalidTemplateId) + { + m_rootInstance->SetTemplateId(Prefab::InvalidTemplateId); + m_prefabSystemComponent->RemoveTemplate(templateId); + } + m_rootInstance->Reset(); + m_rootInstance->SetContainerEntityName("Level"); } - m_rootInstance->Reset(); - m_rootInstance->SetContainerEntityName("Level"); AzFramework::EntityOwnershipServiceNotificationBus::Event( m_entityContextId, &AzFramework::EntityOwnershipServiceNotificationBus::Events::OnEntityOwnershipServiceReset); @@ -202,7 +204,7 @@ namespace AzToolsFramework } m_rootInstance->SetTemplateId(templateId); - m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GetRelativePathToProject(filename)); + m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GenerateRelativePath(filename)); m_rootInstance->SetContainerEntityName("Level"); m_prefabSystemComponent->PropagateTemplateChanges(templateId); @@ -220,7 +222,7 @@ namespace AzToolsFramework bool PrefabEditorEntityOwnershipService::SaveToStream(AZ::IO::GenericStream& stream, AZStd::string_view filename) { - AZ::IO::Path relativePath = m_loaderInterface->GetRelativePathToProject(filename); + AZ::IO::Path relativePath = m_loaderInterface->GenerateRelativePath(filename); AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath); m_rootInstance->SetTemplateSourcePath(relativePath); @@ -267,7 +269,7 @@ namespace AzToolsFramework void PrefabEditorEntityOwnershipService::CreateNewLevelPrefab(AZStd::string_view filename, const AZStd::string& templateFilename) { - AZ::IO::Path relativePath = m_loaderInterface->GetRelativePathToProject(filename); + AZ::IO::Path relativePath = m_loaderInterface->GenerateRelativePath(filename); AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath); m_rootInstance->SetTemplateSourcePath(relativePath); @@ -378,7 +380,12 @@ namespace AzToolsFramework Prefab::InstanceOptionalReference PrefabEditorEntityOwnershipService::GetRootPrefabInstance() { AZ_Assert(m_rootInstance, "A valid root prefab instance couldn't be found in PrefabEditorEntityOwnershipService."); - return *m_rootInstance; + if (m_rootInstance) + { + return *m_rootInstance; + } + + return AZStd::nullopt; } const AZStd::vector>& PrefabEditorEntityOwnershipService::GetPlayInEditorAssetData() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp index 836140eb74..39351df486 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp @@ -124,7 +124,7 @@ namespace AzToolsFramework "PrefabLoaderInterface could not be found. It is required to load Prefab Instances"); // Make sure we have a relative path - instance->m_templateSourcePath = loaderInterface->GetRelativePathToProject(instance->m_templateSourcePath); + instance->m_templateSourcePath = loaderInterface->GenerateRelativePath(instance->m_templateSourcePath); TemplateId templateId = prefabSystemComponentInterface->GetTemplateIdFromFilePath(instance->GetTemplateSourcePath()); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp index 2965148172..e4507227b5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp @@ -18,7 +18,9 @@ #include #include +#include #include +#include #include #include #include @@ -112,7 +114,7 @@ namespace AzToolsFramework return InvalidTemplateId; } - AZ::IO::Path relativePath = GetRelativePathToProject(originPath); + AZ::IO::Path relativePath = GenerateRelativePath(originPath); // Cyclical dependency detected if the prefab file is already part of the progressed // file path set. @@ -385,21 +387,100 @@ namespace AzToolsFramework AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path).MakePreferred(); if (pathWithOSSeparator.IsAbsolute()) { + // If an absolute path was passed in, just return it as-is. return path; } - return AZ::IO::Path(m_projectPathWithOsSeparator).Append(pathWithOSSeparator); + // A relative path was passed in, so try to turn it back into an absolute path. + + AZ::IO::Path fullPath; + + bool pathFound = false; + AZ::Data::AssetInfo assetInfo; + AZStd::string rootFolder; + AZStd::string inputPath(path.Native()); + + // Given an input path that's expected to exist, try to look it up. + AzToolsFramework::AssetSystemRequestBus::BroadcastResult( + pathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, + inputPath.c_str(), assetInfo, rootFolder); + + if (pathFound) + { + // The asset system provided us with a valid root folder and relative path, so return it. + fullPath = AZ::IO::Path(rootFolder) / assetInfo.m_relativePath; + } + else + { + // If for some reason the Asset system couldn't provide a relative path, provide some fallback logic. + + // Check to see if the AssetProcessor is ready. If it *is* and we didn't get a path, print an error then follow + // the fallback logic. If it's *not* ready, we're probably either extremely early in a tool startup flow or inside + // a unit test, so just execute the fallback logic without an error. + [[maybe_unused]] bool assetProcessorReady = false; + AzFramework::AssetSystemRequestBus::BroadcastResult( + assetProcessorReady, &AzFramework::AssetSystemRequestBus::Events::AssetProcessorIsReady); + + AZ_Error( + "Prefab", !assetProcessorReady, "Full source path for '%.*s' could not be determined. Using fallback logic.", + AZ_STRING_ARG(path.Native())); + + // If a relative path was passed in, make it relative to the project root. + fullPath = AZ::IO::Path(m_projectPathWithOsSeparator).Append(pathWithOSSeparator); + } + + return fullPath; } - AZ::IO::Path PrefabLoader::GetRelativePathToProject(AZ::IO::PathView path) + AZ::IO::Path PrefabLoader::GenerateRelativePath(AZ::IO::PathView path) { - AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path.Native()).MakePreferred(); - if (!pathWithOSSeparator.IsAbsolute()) + bool pathFound = false; + + AZStd::string relativePath; + AZStd::string rootFolder; + AZ::IO::Path finalPath; + + // The asset system allows for paths to be relative to multiple root folders, using a priority system. + // This request will make the input path relative to the most appropriate, highest-priority root folder. + AzToolsFramework::AssetSystemRequestBus::BroadcastResult( + pathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GenerateRelativeSourcePath, path.Native(), + relativePath, rootFolder); + + if (pathFound && !relativePath.empty()) { - return path; + // A relative path was generated successfully, so return it. + finalPath = relativePath; + } + else + { + // If for some reason the Asset system couldn't provide a relative path, provide some fallback logic. + + // Check to see if the AssetProcessor is ready. If it *is* and we didn't get a path, print an error then follow + // the fallback logic. If it's *not* ready, we're probably either extremely early in a tool startup flow or inside + // a unit test, so just execute the fallback logic without an error. + [[maybe_unused]] bool assetProcessorReady = false; + AzFramework::AssetSystemRequestBus::BroadcastResult( + assetProcessorReady, &AzFramework::AssetSystemRequestBus::Events::AssetProcessorIsReady); + + AZ_Error("Prefab", !assetProcessorReady, + "Relative source path for '%.*s' could not be determined. Using project path as relative root.", + AZ_STRING_ARG(path.Native())); + + AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path.Native()).MakePreferred(); + + if (pathWithOSSeparator.IsAbsolute()) + { + // If an absolute path was passed in, make it relative to the project path. + finalPath = AZ::IO::Path(path.Native(), '/').MakePreferred().LexicallyRelative(m_projectPathWithSlashSeparator); + } + else + { + // If a relative path was passed in, just return it. + finalPath = path; + } } - return AZ::IO::Path(path.Native(), '/').MakePreferred().LexicallyRelative(m_projectPathWithSlashSeparator); + return finalPath; } AZ::IO::Path PrefabLoaderInterface::GeneratePath() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h index d11cb62ca3..aed24e153e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h @@ -91,9 +91,11 @@ namespace AzToolsFramework //! The path will always have the correct separator for the current OS AZ::IO::Path GetFullPath(AZ::IO::PathView path) override; - //! Converts path into a relative path to the project, this will be the paths in .prefab file. - //! The path will always have '/' separator. - AZ::IO::Path GetRelativePathToProject(AZ::IO::PathView path) override; + //! Converts path into a path that's relative to the highest-priority containing folder of all the folders registered + //! with the engine. + //! This path will be the path that appears in the .prefab file. + //! The path will always use the '/' separator. + AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) override; //! Returns if the path is a valid path for a prefab static bool IsValidPrefabPath(AZ::IO::PathView path); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h index a4055fb15a..d71fbff80f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h @@ -74,9 +74,11 @@ namespace AzToolsFramework //! The path will always have the correct separator for the current OS virtual AZ::IO::Path GetFullPath(AZ::IO::PathView path) = 0; - //! Converts path into a relative path to the current project, this will be the paths in .prefab file. - //! The path will always have '/' separator. - virtual AZ::IO::Path GetRelativePathToProject(AZ::IO::PathView path) = 0; + //! Converts path into a path that's relative to the highest-priority containing folder of all the folders registered + //! with the engine. + //! This path will be the path that appears in the .prefab file. + //! The path will always use the '/' separator. + virtual AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) = 0; protected: diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 0181050a32..9dd5199ea2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -318,7 +318,7 @@ namespace AzToolsFramework } //Detect whether this instantiation would produce a cyclical dependency - auto relativePath = m_prefabLoaderInterface->GetRelativePathToProject(filePath); + auto relativePath = m_prefabLoaderInterface->GenerateRelativePath(filePath); Prefab::TemplateId templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(relativePath); if (templateId == InvalidTemplateId) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index c4e6415b02..0136f791b3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -95,7 +95,7 @@ namespace AzToolsFramework const AZStd::vector& entities, AZStd::vector>&& instancesToConsume, AZ::IO::PathView filePath, AZStd::unique_ptr containerEntity, bool shouldCreateLinks) { - AZ::IO::Path relativeFilePath = m_prefabLoader.GetRelativePathToProject(filePath); + AZ::IO::Path relativeFilePath = m_prefabLoader.GenerateRelativePath(filePath); if (GetTemplateIdFromFilePath(relativeFilePath) != InvalidTemplateId) { AZ_Error("Prefab", false, diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 3edc190fb7..61d4433c0e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -333,7 +333,8 @@ namespace AzToolsFramework } } - auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, s_prefabLoaderInterface->GetRelativePathToProject(prefabFilePath.data())); + auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab( + selectedEntities, s_prefabLoaderInterface->GenerateRelativePath(prefabFilePath.data())); if (!createPrefabOutcome.IsSuccess()) { diff --git a/Code/Tools/SerializeContextTools/SliceConverter.cpp b/Code/Tools/SerializeContextTools/SliceConverter.cpp index 3fbf7cb25c..d06534e303 100644 --- a/Code/Tools/SerializeContextTools/SliceConverter.cpp +++ b/Code/Tools/SerializeContextTools/SliceConverter.cpp @@ -244,7 +244,7 @@ namespace AZ } else { - return SavePrefab(templateId); + return SavePrefab(outputPath, templateId); } } @@ -318,7 +318,7 @@ namespace AZ nestedPrefabPath.ReplaceExtension("prefab"); auto prefabLoaderInterface = AZ::Interface::Get(); - nestedPrefabPath = prefabLoaderInterface->GetRelativePathToProject(nestedPrefabPath); + nestedPrefabPath = prefabLoaderInterface->GenerateRelativePath(nestedPrefabPath); AzToolsFramework::Prefab::TemplateId nestedTemplateId = prefabSystemComponentInterface->GetTemplateIdFromFilePath(nestedPrefabPath); @@ -439,17 +439,31 @@ namespace AZ AZ::Debug::Trace::Instance().Output("", "\n"); } - bool SliceConverter::SavePrefab(AzToolsFramework::Prefab::TemplateId templateId) + bool SliceConverter::SavePrefab(AZ::IO::PathView outputPath, AzToolsFramework::Prefab::TemplateId templateId) { auto prefabLoaderInterface = AZ::Interface::Get(); - if (!prefabLoaderInterface->SaveTemplate(templateId)) + AZStd::string out; + if (prefabLoaderInterface->SaveTemplateToString(templateId, out)) { - AZ_Printf("Convert-Slice", " Could not save prefab - internal error (Json write operation failure).\n"); - return false; + IO::SystemFile outputFile; + if (!outputFile.Open( + AZStd::string(outputPath.Native()).c_str(), + IO::SystemFile::OpenMode::SF_OPEN_CREATE | + IO::SystemFile::OpenMode::SF_OPEN_CREATE_PATH | + IO::SystemFile::OpenMode::SF_OPEN_WRITE_ONLY)) + { + AZ_Error("Convert-Slice", false, " Unable to create output file '%.*s'.", AZ_STRING_ARG(outputPath.Native())); + return false; + } + + outputFile.Write(out.data(), out.size()); + outputFile.Close(); + return true; } - return true; + AZ_Printf("Convert-Slice", " Could not save prefab - internal error (Json write operation failure).\n"); + return false; } bool SliceConverter::ConnectToAssetProcessor() diff --git a/Code/Tools/SerializeContextTools/SliceConverter.h b/Code/Tools/SerializeContextTools/SliceConverter.h index a977095f02..bec893ff56 100644 --- a/Code/Tools/SerializeContextTools/SliceConverter.h +++ b/Code/Tools/SerializeContextTools/SliceConverter.h @@ -56,7 +56,7 @@ namespace AZ AZ::SliceComponent::SliceInstance& instance, AZ::Data::Asset& sliceAsset, AzToolsFramework::Prefab::TemplateReference nestedTemplate, AzToolsFramework::Prefab::Instance* topLevelInstance); static void PrintPrefab(AzToolsFramework::Prefab::TemplateId templateId); - static bool SavePrefab(AzToolsFramework::Prefab::TemplateId templateId); + static bool SavePrefab(AZ::IO::PathView outputPath, AzToolsFramework::Prefab::TemplateId templateId); }; } // namespace SerializeContextTools } // namespace AZ From 2b35ed1d7f005603fb7cc524ae06170db11d4ca7 Mon Sep 17 00:00:00 2001 From: moudgils Date: Fri, 28 May 2021 08:50:27 -0700 Subject: [PATCH 32/41] Fixes to get monolithic builds working for ios --- Code/LauncherUnified/launcher_generator.cmake | 2 ++ .../AtomViewportDisplayInfo/Code/CMakeLists.txt | 2 +- cmake/Tools/common.py | 6 +++--- cmake/Tools/layout_tool.py | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Code/LauncherUnified/launcher_generator.cmake b/Code/LauncherUnified/launcher_generator.cmake index edb6655411..c5d60eb29e 100644 --- a/Code/LauncherUnified/launcher_generator.cmake +++ b/Code/LauncherUnified/launcher_generator.cmake @@ -179,6 +179,7 @@ function(ly_delayed_generate_static_modules_inl) ${launcher_unified_binary_dir}/${project_name}.GameLauncher/Includes/StaticModules.inl ) + ly_target_link_libraries(${project_name}.GameLauncher PRIVATE ${all_game_gem_dependencies}) if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) get_property(server_gem_dependencies GLOBAL PROPERTY LY_STATIC_MODULE_PROJECTS_DEPENDENCIES_${project_name}.ServerLauncher) @@ -204,6 +205,7 @@ function(ly_delayed_generate_static_modules_inl) ${launcher_unified_binary_dir}/${project_name}.ServerLauncher/Includes/StaticModules.inl ) + ly_target_link_libraries(${project_name}.ServerLauncher PRIVATE ${all_server_gem_dependencies}) endif() endforeach() endif() diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt index de4ee9b4b5..0f134d4218 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt @@ -10,7 +10,7 @@ # ly_add_target( - NAME AtomViewportDisplayInfo GEM_MODULE + NAME AtomViewportDisplayInfo ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} NAMESPACE Gem FILES_CMAKE atomviewportdisplayinfo_files.cmake diff --git a/cmake/Tools/common.py b/cmake/Tools/common.py index 8189bb3ca3..c6a3e89e67 100755 --- a/cmake/Tools/common.py +++ b/cmake/Tools/common.py @@ -149,7 +149,7 @@ def get_bootstrap_values(bootstrap_dir, keys_to_extract): raise logging.error(f'Bootstrap.setreg file {bootstrap_file} does not exist.') result_map = {} - with bootstrap_file.open('r') as f: + with open(bootstrap_file, 'r') as f: try: json_data = json.load(f) except Exception as e: @@ -157,9 +157,9 @@ def get_bootstrap_values(bootstrap_dir, keys_to_extract): else: for search_key in keys_to_extract: try: - search_result = json_data["Amazon"]["AzCore"]["Bootstrap"][f'"{search_key}"'] + search_result = json_data["Amazon"]["AzCore"]["Bootstrap"][search_key] except KeyError as e: - logging.error(f'Bootstrap.setreg cannot find Amazon:AzCore:Bootstrap:{search_result}: {str(e)}') + logging.warning(f'Bootstrap.setreg cannot find /Amazon/AzCore/Bootstrap/{search_key}: {str(e)}') else: result_map[search_key] = search_result diff --git a/cmake/Tools/layout_tool.py b/cmake/Tools/layout_tool.py index 69f5b34ae7..3fcab241d7 100755 --- a/cmake/Tools/layout_tool.py +++ b/cmake/Tools/layout_tool.py @@ -107,7 +107,7 @@ def verify_layout(layout_dir, platform_name, project_path, asset_mode, asset_typ project_name_lower = project_path.lower() layout_path = pathlib.Path(layout_dir) - bootstrap_path = layout_path / 'Registry' + bootstrap_path = pathlib.Path(ROOT_ENGINE_PATH) / 'Registry' bootstrap_values = common.get_bootstrap_values(str(bootstrap_path), [f'{platform_name_lower}_remote_filesystem', f'{platform_name_lower}_connect_to_remote', f'{platform_name_lower}_wait_for_connect', From 1b1a8c0c951fc399dee5c97dea49fe4a80d98160 Mon Sep 17 00:00:00 2001 From: moudgils Date: Fri, 28 May 2021 08:55:03 -0700 Subject: [PATCH 33/41] Reverting changes not related to this PR --- .../Shaders/PostProcessing/LuminanceHistogramGenerator.azsl | 2 +- .../Shaders/PostProcessing/LuminanceHistogramGenerator.shader | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl index 9d01a12fd6..05cc870eea 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.azsl @@ -20,7 +20,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass { Texture2D m_inputTexture; - RWStructuredBuffer m_outputTexture; + RWBuffer m_outputTexture; } groupshared uint shared_histogramBins[NUM_HISTOGRAM_BINS]; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader index f3dd11e11a..10f94cbff6 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader @@ -12,5 +12,6 @@ "type": "Compute" } ] - } + }, + "DisabledRHIBackends": ["metal"] } From 86a00c4679dbd85f218a1fa304e35e6f8f18781e Mon Sep 17 00:00:00 2001 From: moudgils Date: Fri, 28 May 2021 08:57:05 -0700 Subject: [PATCH 34/41] Reverting a minor change --- .../Shaders/PostProcessing/LuminanceHistogramGenerator.shader | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader index 10f94cbff6..f9040060d6 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader @@ -14,4 +14,5 @@ ] }, "DisabledRHIBackends": ["metal"] + } From 6a81dbe2585eb38eda0f84ed63c26b66b02048c6 Mon Sep 17 00:00:00 2001 From: moudgils Date: Fri, 28 May 2021 08:59:11 -0700 Subject: [PATCH 35/41] Reverting Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader --- .../Shaders/PostProcessing/LuminanceHistogramGenerator.shader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader index f9040060d6..566144bab8 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/LuminanceHistogramGenerator.shader @@ -14,5 +14,5 @@ ] }, "DisabledRHIBackends": ["metal"] - + } From 96080d85e4f1fce178998afd991f56f4d84f2eeb Mon Sep 17 00:00:00 2001 From: AMZN-nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Fri, 28 May 2021 09:32:47 -0700 Subject: [PATCH 36/41] Project Manager Support Add Existing Projects, Removing, Copying, and Deleting (#961) * Add Add/RemoveProject to Python Bindings * Support Project, Add, Remove, Copy, Delete * Open parent directory when duplicating to discourage path in owning dir * Remove extra connects for new projects button * Center project image --- .../Source/ProjectButtonWidget.cpp | 43 ++-- .../Source/ProjectButtonWidget.h | 9 +- .../ProjectManager/Source/ProjectUtils.cpp | 196 ++++++++++++++++++ .../ProjectManager/Source/ProjectUtils.h | 28 +++ .../ProjectManager/Source/ProjectsScreen.cpp | 57 +++-- .../ProjectManager/Source/PythonBindings.cpp | 63 +++++- .../ProjectManager/Source/PythonBindings.h | 2 + .../Source/PythonBindingsInterface.h | 14 ++ .../project_manager_files.cmake | 2 + 9 files changed, 359 insertions(+), 55 deletions(-) create mode 100644 Code/Tools/ProjectManager/Source/ProjectUtils.cpp create mode 100644 Code/Tools/ProjectManager/Source/ProjectUtils.h diff --git a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp index 4be876e79f..72ffa686c1 100644 --- a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp @@ -12,6 +12,7 @@ #include + #include #include #include @@ -58,19 +59,15 @@ namespace O3DE::ProjectManager m_overlayLabel->setText(text); } - ProjectButton::ProjectButton(const QString& projectName, QWidget* parent) + ProjectButton::ProjectButton(const ProjectInfo& projectInfo, QWidget* parent) : QFrame(parent) - , m_projectName(projectName) - , m_projectImagePath(":/Resources/DefaultProjectImage.png") + , m_projectInfo(projectInfo) { - Setup(); - } + if (m_projectInfo.m_imagePath.isEmpty()) + { + m_projectInfo.m_imagePath = ":/DefaultProjectImage.png"; + } - ProjectButton::ProjectButton(const QString& projectName, const QString& projectImage, QWidget* parent) - : QFrame(parent) - , m_projectName(projectName) - , m_projectImagePath(projectImage) - { Setup(); } @@ -85,20 +82,22 @@ namespace O3DE::ProjectManager m_projectImageLabel = new LabelButton(this); m_projectImageLabel->setFixedSize(s_projectImageWidth, s_projectImageHeight); + m_projectImageLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); vLayout->addWidget(m_projectImageLabel); - m_projectImageLabel->setPixmap(QPixmap(m_projectImagePath).scaled(m_projectImageLabel->size(), Qt::KeepAspectRatioByExpanding)); + m_projectImageLabel->setPixmap( + QPixmap(m_projectInfo.m_imagePath).scaled(m_projectImageLabel->size(), Qt::KeepAspectRatioByExpanding)); QMenu* newProjectMenu = new QMenu(this); m_editProjectAction = newProjectMenu->addAction(tr("Edit Project Settings...")); - -#ifdef SHOW_ALL_PROJECT_ACTIONS - m_editProjectGemsAction = newProjectMenu->addAction(tr("Cutomize Gems...")); newProjectMenu->addSeparator(); m_copyProjectAction = newProjectMenu->addAction(tr("Duplicate")); newProjectMenu->addSeparator(); m_removeProjectAction = newProjectMenu->addAction(tr("Remove from O3DE")); - m_deleteProjectAction = newProjectMenu->addAction(tr("Delete the Project")); + m_deleteProjectAction = newProjectMenu->addAction(tr("Delete this Project")); + +#ifdef SHOW_ALL_PROJECT_ACTIONS + m_editProjectGemsAction = newProjectMenu->addAction(tr("Cutomize Gems...")); #endif QFrame* footer = new QFrame(this); @@ -106,7 +105,7 @@ namespace O3DE::ProjectManager hLayout->setContentsMargins(0, 0, 0, 0); footer->setLayout(hLayout); { - QLabel* projectNameLabel = new QLabel(m_projectName, this); + QLabel* projectNameLabel = new QLabel(m_projectInfo.m_displayName, this); hLayout->addWidget(projectNameLabel); QPushButton* projectMenuButton = new QPushButton(this); @@ -117,14 +116,14 @@ namespace O3DE::ProjectManager vLayout->addWidget(footer); - connect(m_projectImageLabel, &LabelButton::triggered, [this]() { emit OpenProject(m_projectName); }); - connect(m_editProjectAction, &QAction::triggered, [this]() { emit EditProject(m_projectName); }); + connect(m_projectImageLabel, &LabelButton::triggered, [this]() { emit OpenProject(m_projectInfo.m_path); }); + connect(m_editProjectAction, &QAction::triggered, [this]() { emit EditProject(m_projectInfo.m_path); }); + connect(m_copyProjectAction, &QAction::triggered, [this]() { emit CopyProject(m_projectInfo.m_path); }); + connect(m_removeProjectAction, &QAction::triggered, [this]() { emit RemoveProject(m_projectInfo.m_path); }); + connect(m_deleteProjectAction, &QAction::triggered, [this]() { emit DeleteProject(m_projectInfo.m_path); }); #ifdef SHOW_ALL_PROJECT_ACTIONS - connect(m_editProjectGemsAction, &QAction::triggered, [this]() { emit EditProjectGems(m_projectName); }); - connect(m_copyProjectAction, &QAction::triggered, [this]() { emit CopyProject(m_projectName); }); - connect(m_removeProjectAction, &QAction::triggered, [this]() { emit RemoveProject(m_projectName); }); - connect(m_deleteProjectAction, &QAction::triggered, [this]() { emit DeleteProject(m_projectName); }); + connect(m_editProjectGemsAction, &QAction::triggered, [this]() { emit EditProjectGems(m_projectInfo.m_path); }); #endif } diff --git a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h index 671debf6d0..e82b56b3fa 100644 --- a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h +++ b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h @@ -13,7 +13,8 @@ #pragma once #if !defined(Q_MOC_RUN) -#include +#include + #include #endif @@ -52,8 +53,7 @@ namespace O3DE::ProjectManager Q_OBJECT // AUTOMOC public: - explicit ProjectButton(const QString& projectName, QWidget* parent = nullptr); - explicit ProjectButton(const QString& projectName, const QString& projectImage, QWidget* parent = nullptr); + explicit ProjectButton(const ProjectInfo& m_projectInfo, QWidget* parent = nullptr); ~ProjectButton() = default; void SetButtonEnabled(bool enabled); @@ -70,8 +70,7 @@ namespace O3DE::ProjectManager private: void Setup(); - QString m_projectName; - QString m_projectImagePath; + ProjectInfo m_projectInfo; LabelButton* m_projectImageLabel; QAction* m_editProjectAction; QAction* m_editProjectGemsAction; diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp new file mode 100644 index 0000000000..526e745d82 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp @@ -0,0 +1,196 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include + +#include +#include +#include +#include + +namespace O3DE::ProjectManager +{ + namespace ProjectUtils + { + static bool WarnDirectoryOverwrite(const QString& path, QWidget* parent) + { + if (!QDir(path).isEmpty()) + { + QMessageBox::StandardButton warningResult = QMessageBox::warning( + parent, + QObject::tr("Overwrite Directory"), + QObject::tr("Directory is not empty! Are you sure you want to overwrite it?"), + QMessageBox::No | QMessageBox::Yes + ); + + if (warningResult != QMessageBox::Yes) + { + return false; + } + } + + return true; + } + + static bool IsDirectoryDescedent(const QString& possibleAncestorPath, const QString& possibleDecedentPath) + { + QDir ancestor(possibleAncestorPath); + QDir descendent(possibleDecedentPath); + + do + { + if (ancestor == descendent) + { + return false; + } + + descendent.cdUp(); + } + while (!descendent.isRoot()); + + return true; + } + + static bool CopyDirectory(const QString& origPath, const QString& newPath) + { + QDir original(origPath); + if (!original.exists()) + { + return false; + } + + for (QString directory : original.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) + { + QString newDirectoryPath = newPath + QDir::separator() + directory; + original.mkpath(newDirectoryPath); + + if (!CopyDirectory(origPath + QDir::separator() + directory, newDirectoryPath)) + { + return false; + } + } + + for (QString file : original.entryList(QDir::Files)) + { + if (!QFile::copy(origPath + QDir::separator() + file, newPath + QDir::separator() + file)) + return false; + } + + return true; + } + + bool AddProjectDialog(QWidget* parent) + { + QString path = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(parent, QObject::tr("Select Project Directory"))); + if (!path.isEmpty()) + { + return RegisterProject(path); + } + + return false; + } + + bool RegisterProject(const QString& path) + { + return PythonBindingsInterface::Get()->AddProject(path); + } + + bool UnregisterProject(const QString& path) + { + return PythonBindingsInterface::Get()->RemoveProject(path); + } + + bool CopyProjectDialog(const QString& origPath, QWidget* parent) + { + bool copyResult = false; + + QDir parentOrigDir(origPath); + parentOrigDir.cdUp(); + QString newPath = QDir::toNativeSeparators( + QFileDialog::getExistingDirectory(parent, QObject::tr("Select New Project Directory"), parentOrigDir.path())); + if (!newPath.isEmpty()) + { + if (!WarnDirectoryOverwrite(newPath, parent)) + { + return false; + } + + // TODO: Block UX and Notify User they need to wait + + copyResult = CopyProject(origPath, newPath); + } + + return copyResult; + } + + bool CopyProject(const QString& origPath, const QString& newPath) + { + // Disallow copying from or into subdirectory + if (!IsDirectoryDescedent(origPath, newPath) || !IsDirectoryDescedent(newPath, origPath)) + { + return false; + } + + if (!CopyDirectory(origPath, newPath)) + { + // Cleanup whatever mess was made + DeleteProjectFiles(newPath, true); + return false; + } + + if (!RegisterProject(newPath)) + { + DeleteProjectFiles(newPath, true); + } + + return true; + } + + bool DeleteProjectFiles(const QString& path, bool force) + { + QDir projectDirectory(path); + if (projectDirectory.exists()) + { + // Check if there is an actual project hereor just force it + if (force || PythonBindingsInterface::Get()->GetProject(path).IsSuccess()) + { + return projectDirectory.removeRecursively(); + } + } + + return false; + } + + bool MoveProject(const QString& origPath, const QString& newPath, QWidget* parent) + { + if (!WarnDirectoryOverwrite(newPath, parent) || !UnregisterProject(origPath)) + { + return false; + } + + QDir directory; + if (directory.rename(origPath, newPath)) + { + return directory.rename(origPath, newPath); + } + + if (!RegisterProject(newPath)) + { + return false; + } + + return true; + } + + } // namespace ProjectUtils +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.h b/Code/Tools/ProjectManager/Source/ProjectUtils.h new file mode 100644 index 0000000000..5982bff634 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/ProjectUtils.h @@ -0,0 +1,28 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ +#pragma once + +#include + +namespace O3DE::ProjectManager +{ + namespace ProjectUtils + { + bool AddProjectDialog(QWidget* parent = nullptr); + bool RegisterProject(const QString& path); + bool UnregisterProject(const QString& path); + bool CopyProjectDialog(const QString& origPath, QWidget* parent = nullptr); + bool CopyProject(const QString& origPath, const QString& newPath); + bool DeleteProjectFiles(const QString& path, bool force = false); + bool MoveProject(const QString& origPath, const QString& newPath, QWidget* parent = nullptr); + } // namespace ProjectUtils +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp index 5f1c0e2b36..dd2e411ec5 100644 --- a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -65,9 +66,6 @@ namespace O3DE::ProjectManager m_stack->addWidget(m_projectsContent); vLayout->addWidget(m_stack); - - connect(m_createNewProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleNewProjectButton); - connect(m_addExistingProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleAddProjectButton); } QFrame* ProjectsScreen::CreateFirstTimeContent() @@ -167,28 +165,27 @@ namespace O3DE::ProjectManager #endif { ProjectButton* projectButton; + QString projectPreviewPath = project.m_path + m_projectPreviewImagePath; QFileInfo doesPreviewExist(projectPreviewPath); if (doesPreviewExist.exists() && doesPreviewExist.isFile()) { - projectButton = new ProjectButton(project.m_projectName, projectPreviewPath, this); - } - else - { - projectButton = new ProjectButton(project.m_projectName, this); + project.m_imagePath = projectPreviewPath; } + projectButton = new ProjectButton(project, this); + flowLayout->addWidget(projectButton); connect(projectButton, &ProjectButton::OpenProject, this, &ProjectsScreen::HandleOpenProject); connect(projectButton, &ProjectButton::EditProject, this, &ProjectsScreen::HandleEditProject); - - #ifdef DISPLAY_PROJECT_DEV_DATA - connect(projectButton, &ProjectButton::EditProjectGems, this, &ProjectsScreen::HandleEditProjectGems); connect(projectButton, &ProjectButton::CopyProject, this, &ProjectsScreen::HandleCopyProject); connect(projectButton, &ProjectButton::RemoveProject, this, &ProjectsScreen::HandleRemoveProject); connect(projectButton, &ProjectButton::DeleteProject, this, &ProjectsScreen::HandleDeleteProject); - #endif + +#ifdef SHOW_ALL_PROJECT_ACTIONS + connect(projectButton, &ProjectButton::EditProjectGems, this, &ProjectsScreen::HandleEditProjectGems); +#endif } layout->addWidget(projectsScrollArea); @@ -242,7 +239,11 @@ namespace O3DE::ProjectManager } void ProjectsScreen::HandleAddProjectButton() { - // Do nothing for now + if (ProjectUtils::AddProjectDialog(this)) + { + emit ResetScreenRequest(ProjectManagerScreen::Projects); + emit ChangeScreenRequest(ProjectManagerScreen::Projects); + } } void ProjectsScreen::HandleOpenProject(const QString& projectPath) { @@ -300,18 +301,36 @@ namespace O3DE::ProjectManager emit NotifyCurrentProject(projectPath); emit ChangeScreenRequest(ProjectManagerScreen::GemCatalog); } - void ProjectsScreen::HandleCopyProject([[maybe_unused]] const QString& projectPath) + void ProjectsScreen::HandleCopyProject(const QString& projectPath) { // Open file dialog and choose location for copied project then register copy with O3DE + if (ProjectUtils::CopyProjectDialog(projectPath, this)) + { + emit ResetScreenRequest(ProjectManagerScreen::Projects); + emit ChangeScreenRequest(ProjectManagerScreen::Projects); + } } - void ProjectsScreen::HandleRemoveProject([[maybe_unused]] const QString& projectPath) + void ProjectsScreen::HandleRemoveProject(const QString& projectPath) { - // Unregister Project from O3DE + // Unregister Project from O3DE and reload projects + if (ProjectUtils::UnregisterProject(projectPath)) + { + emit ResetScreenRequest(ProjectManagerScreen::Projects); + emit ChangeScreenRequest(ProjectManagerScreen::Projects); + } } - void ProjectsScreen::HandleDeleteProject([[maybe_unused]] const QString& projectPath) + void ProjectsScreen::HandleDeleteProject(const QString& projectPath) { - // Remove project from 03DE and delete from disk - ProjectsScreen::HandleRemoveProject(projectPath); + QMessageBox::StandardButton warningResult = QMessageBox::warning( + this, tr("Delete Project"), tr("Are you sure?\nProject will be removed from O3DE and directory will be deleted!"), + QMessageBox::No | QMessageBox::Yes); + + if (warningResult == QMessageBox::Yes) + { + // Remove project from O3DE and delete from disk + HandleRemoveProject(projectPath); + ProjectUtils::DeleteProjectFiles(projectPath); + } } void ProjectsScreen::NotifyCurrentScreen() diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 8c79a153c8..9279ad1291 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -379,13 +379,13 @@ namespace O3DE::ProjectManager pybind11::str defaultTemplatesFolder = engineInfo.m_defaultTemplatesFolder.toStdString(); auto registrationResult = m_registration.attr("register")( - enginePath, // engine_path - pybind11::none(), // project_path - pybind11::none(), // gem_path - pybind11::none(), // template_path - pybind11::none(), // restricted_path - pybind11::none(), // repo_uri - pybind11::none(), // default_engines_folder + enginePath, // engine_path + pybind11::none(), // project_path + pybind11::none(), // gem_path + pybind11::none(), // template_path + pybind11::none(), // restricted_path + pybind11::none(), // repo_uri + pybind11::none(), // default_engines_folder defaultProjectsFolder, defaultGemsFolder, defaultTemplatesFolder @@ -456,6 +456,51 @@ namespace O3DE::ProjectManager } } + bool PythonBindings::AddProject(const QString& path) + { + bool registrationResult = false; + bool result = ExecuteWithLock( + [&] + { + pybind11::str projectPath = path.toStdString(); + auto pythonRegistrationResult = m_registration.attr("register")(pybind11::none(), projectPath); + + // Returns an exit code so boolify it then invert result + registrationResult = !pythonRegistrationResult.cast(); + }); + + return result && registrationResult; + } + + bool PythonBindings::RemoveProject(const QString& path) + { + bool registrationResult = false; + bool result = ExecuteWithLock( + [&] + { + pybind11::str projectPath = path.toStdString(); + auto pythonRegistrationResult = m_registration.attr("register")( + pybind11::none(), // engine_path + projectPath, // project_path + pybind11::none(), // gem_path + pybind11::none(), // template_path + pybind11::none(), // restricted_path + pybind11::none(), // repo_uri + pybind11::none(), // default_engines_folder + pybind11::none(), // default_gems_folder + pybind11::none(), // default_templates_folder + pybind11::none(), // default_restricted_folder + pybind11::none(), // default_restricted_folder + true // remove + ); + + // Returns an exit code so boolify it then invert result + registrationResult = !pythonRegistrationResult.cast(); + }); + + return result && registrationResult; + } + AZ::Outcome PythonBindings::CreateProject(const QString& projectTemplatePath, const ProjectInfo& projectInfo) { ProjectInfo createdProjectInfo; @@ -600,7 +645,7 @@ namespace O3DE::ProjectManager pybind11::none(), // gem_target pybind11::none(), // project_name pyProjectPath - ); + ); }); return result; @@ -618,7 +663,7 @@ namespace O3DE::ProjectManager pybind11::none(), // gem_target pybind11::none(), // project_name pyProjectPath - ); + ); }); return result; diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.h b/Code/Tools/ProjectManager/Source/PythonBindings.h index 892e13a65b..fb2303c495 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.h +++ b/Code/Tools/ProjectManager/Source/PythonBindings.h @@ -46,6 +46,8 @@ namespace O3DE::ProjectManager AZ::Outcome CreateProject(const QString& projectTemplatePath, const ProjectInfo& projectInfo) override; AZ::Outcome GetProject(const QString& path) override; AZ::Outcome> GetProjects() override; + bool AddProject(const QString& path) override; + bool RemoveProject(const QString& path) override; bool UpdateProject(const ProjectInfo& projectInfo) override; bool AddGemToProject(const QString& gemPath, const QString& projectPath) override; bool RemoveGemFromProject(const QString& gemPath, const QString& projectPath) override; diff --git a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h index b5c8f1a76a..a58eea0fe6 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h +++ b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h @@ -88,6 +88,20 @@ namespace O3DE::ProjectManager * @return an outcome with ProjectInfos on success */ virtual AZ::Outcome> GetProjects() = 0; + + /** + * Adds existing project on disk + * @param path the absolute path to the project + * @return true on success, false on failure + */ + virtual bool AddProject(const QString& path) = 0; + + /** + * Adds existing project on disk + * @param path the absolute path to the project + * @return true on success, false on failure + */ + virtual bool RemoveProject(const QString& path) = 0; /** * Update a project diff --git a/Code/Tools/ProjectManager/project_manager_files.cmake b/Code/Tools/ProjectManager/project_manager_files.cmake index 223465f3c8..feaea4c172 100644 --- a/Code/Tools/ProjectManager/project_manager_files.cmake +++ b/Code/Tools/ProjectManager/project_manager_files.cmake @@ -36,6 +36,8 @@ set(FILES Source/PythonBindingsInterface.h Source/ProjectInfo.h Source/ProjectInfo.cpp + Source/ProjectUtils.h + Source/ProjectUtils.cpp Source/NewProjectSettingsScreen.h Source/NewProjectSettingsScreen.cpp Source/CreateProjectCtrl.h From c630ece43a2cc5c8fda029b5154d575321de58e8 Mon Sep 17 00:00:00 2001 From: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> Date: Fri, 28 May 2021 09:42:11 -0700 Subject: [PATCH 37/41] Add m_linearDepthTexture as input for transparent pass. This is required by popcornfx and it doesn't add extra cost to the render pipeline. --- .../Feature/Common/Assets/Passes/LowEndPipeline.pass | 7 +++++++ .../Feature/Common/Assets/Passes/MainPipeline.pass | 7 +++++++ .../Feature/Common/Assets/Passes/Transparent.pass | 6 ++++++ .../Common/Assets/Passes/TransparentParent.pass | 11 +++++++++++ .../Atom/Features/PBR/TransparentPassSrg.azsli | 1 + 5 files changed, 32 insertions(+) diff --git a/Gems/Atom/Feature/Common/Assets/Passes/LowEndPipeline.pass b/Gems/Atom/Feature/Common/Assets/Passes/LowEndPipeline.pass index b19569fb9d..38a4524aa2 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/LowEndPipeline.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/LowEndPipeline.pass @@ -243,6 +243,13 @@ "Attachment": "LightListRemapped" } }, + { + "LocalSlot": "InputLinearDepth", + "AttachmentRef": { + "Pass": "DepthPrePass", + "Attachment": "DepthLinear" + } + }, { "LocalSlot": "DepthStencil", "AttachmentRef": { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass b/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass index ee943f6d39..af7408b48c 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass @@ -251,6 +251,13 @@ "Attachment": "LightListRemapped" } }, + { + "LocalSlot": "InputLinearDepth", + "AttachmentRef": { + "Pass": "DepthPrePass", + "Attachment": "DepthLinear" + } + }, { "LocalSlot": "DepthStencil", "AttachmentRef": { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/Transparent.pass b/Gems/Atom/Feature/Common/Assets/Passes/Transparent.pass index 415aa2fec0..3bb184a1f8 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/Transparent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/Transparent.pass @@ -67,6 +67,12 @@ "ShaderInputName": "m_lightListRemapped", "ScopeAttachmentUsage": "Shader" }, + { + "Name": "InputLinearDepth", + "SlotType": "Input", + "ShaderInputName": "m_linearDepthTexture", + "ScopeAttachmentUsage": "Shader" + }, // Input/Outputs { "Name": "DepthStencil", diff --git a/Gems/Atom/Feature/Common/Assets/Passes/TransparentParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/TransparentParent.pass index 32517484f3..b278f2bcb4 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/TransparentParent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/TransparentParent.pass @@ -32,6 +32,10 @@ "Name": "LightListRemapped", "SlotType": "Input" }, + { + "Name": "InputLinearDepth", + "SlotType": "Input" + }, // Input/Outputs... { "Name": "DepthStencil", @@ -91,6 +95,13 @@ "Attachment": "LightListRemapped" } }, + { + "LocalSlot": "InputLinearDepth", + "AttachmentRef": { + "Pass": "Parent", + "Attachment": "InputLinearDepth" + } + }, // Input/Outputs... { "LocalSlot": "DepthStencil", diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/TransparentPassSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/TransparentPassSrg.azsli index 14cff21739..d9367f9d03 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/TransparentPassSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/TransparentPassSrg.azsli @@ -35,4 +35,5 @@ ShaderResourceGroup PassSrg : SRG_PerPass Texture2D m_tileLightData; StructuredBuffer m_lightListRemapped; + Texture2D m_linearDepthTexture; } From e73541c75115636513bab4aea5df1b78ce839ecb Mon Sep 17 00:00:00 2001 From: Terry Michaels Date: Fri, 28 May 2021 12:23:49 -0500 Subject: [PATCH 38/41] Allow selected click to edit entity names in the outliner (#1028) --- .../UI/Outliner/EntityOutlinerWidget.cpp | 9 +++++++-- .../UI/Outliner/EntityOutlinerWidget.hxx | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp index cc65b61908..8293614525 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp @@ -172,7 +172,7 @@ namespace AzToolsFramework const int autoExpandDelayMilliseconds = 2500; m_gui->m_objectTree->setSelectionMode(QAbstractItemView::ExtendedSelection); - m_gui->m_objectTree->setEditTriggers(QAbstractItemView::EditKeyPressed); + SetDefaultTreeViewEditTriggers(); m_gui->m_objectTree->setAutoExpandDelay(autoExpandDelayMilliseconds); m_gui->m_objectTree->setDragEnabled(true); m_gui->m_objectTree->setDropIndicatorShown(true); @@ -850,6 +850,11 @@ namespace AzToolsFramework addAction(m_actionGoToEntitiesInViewport); } + void EntityOutlinerWidget::SetDefaultTreeViewEditTriggers() + { + m_gui->m_objectTree->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::EditKeyPressed); + } + void EntityOutlinerWidget::OnEntityPickModeStarted() { m_gui->m_objectTree->setDragEnabled(false); @@ -862,7 +867,7 @@ namespace AzToolsFramework { m_gui->m_objectTree->setDragEnabled(true); m_gui->m_objectTree->setSelectionMode(QAbstractItemView::ExtendedSelection); - m_gui->m_objectTree->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed); + SetDefaultTreeViewEditTriggers(); m_inObjectPickMode = false; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx index 9a02febab2..6e3979a21e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx @@ -166,6 +166,8 @@ namespace AzToolsFramework // to a given entity void QueueScrollToNewContent(const AZ::EntityId& entityId) override; + void SetDefaultTreeViewEditTriggers(); + void ScrollToNewContent(); bool m_scrollToNewContentQueued; bool m_scrollToSelectedEntity; From 1369e29c73308fde5df1d28ca7bfc90af0fbc32f Mon Sep 17 00:00:00 2001 From: AMZN-stankowi Date: Fri, 28 May 2021 10:44:20 -0700 Subject: [PATCH 39/41] =?UTF-8?q?Abort=20calls=20in=20AssImp,=20which=20oc?= =?UTF-8?q?cur=20when=20an=20assert=20is=20hit=20in=20builds=20th=E2=80=A6?= =?UTF-8?q?=20(#1012)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Abort calls in AssImp, which occur when an assert is hit in builds that have asserts enabled (like debug) no longer generate a popup. Instead, they are captured as errors and an asset processing failure. * Added missing include * Added check for _WRITE_ABORT_MSG, so platforms that don't have it but have signals enabled (Linux profile) compile correctly --- .../SDKWrapper/AssImpSceneWrapper.cpp | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp index 2cda1e68ae..791af4bf68 100644 --- a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp +++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp @@ -17,6 +17,13 @@ #include #include +#if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL +#include +#include +#include +#include +#endif // AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL + namespace AZ { namespace AssImpSDKWrapper @@ -34,10 +41,31 @@ namespace AZ { } +#if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL + void signal_handler(int signal) + { + AZ_TracePrintf( + SceneAPI::Utilities::ErrorWindow, + "Failed to import scene with Asset Importer library. An %s has occured in the library, this scene file cannot be parsed by the library.", + signal == SIGABRT ? "assert" : "unknown error"); + } +#endif // AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL + bool AssImpSceneWrapper::LoadSceneFromFile(const char* fileName) { AZ_TracePrintf(SceneAPI::Utilities::LogWindow, "AssImpSceneWrapper::LoadSceneFromFile %s", fileName); AZ_TraceContext("Filename", fileName); + +#if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL + // Turn off the abort popup because it can disrupt automation. + // AssImp calls abort when asserts are enabled, and an assert is encountered. +#ifdef _WRITE_ABORT_MSG + _set_abort_behavior(0, _WRITE_ABORT_MSG); +#endif // #ifdef _WRITE_ABORT_MSG + // Instead, capture any calls to abort with a signal handler, and report them. + auto previous_handler = std::signal(SIGABRT, signal_handler); +#endif // AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL + // aiProcess_JoinIdenticalVertices is not enabled because O3DE has a mesh optimizer that also does this, // this flag is disabled to keep AssImp output similar to FBX SDK to reduce downstream bugs for the initial AssImp release. // There's currently a minimum of properties and flags set to maximize compatibility with the existing node graph. @@ -49,6 +77,15 @@ namespace AZ | aiProcess_LimitBoneWeights //Limits the number of bones that can affect a vertex to a maximum value //dropping the least important and re-normalizing | aiProcess_GenNormals); //Generate normals for meshes + +#if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL + // Reset abort behavior for anything else that may call abort. + std::signal(SIGABRT, previous_handler); +#ifdef _WRITE_ABORT_MSG + _set_abort_behavior(1, _WRITE_ABORT_MSG); +#endif // #ifdef _WRITE_ABORT_MSG +#endif // AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL + if (!m_assImpScene) { AZ_TracePrintf(SceneAPI::Utilities::ErrorWindow, "Failed to import Asset Importer Scene. Error returned: %s", m_importer.GetErrorString()); From 19dc993331ff092149b5066e0a074a470a6e8399 Mon Sep 17 00:00:00 2001 From: sharmajs-amzn <82233357+sharmajs-amzn@users.noreply.github.com> Date: Fri, 28 May 2021 10:47:38 -0700 Subject: [PATCH 40/41] {SPEC-6465} DeltaCatalog.xml does not contain value (#935) * fixes for Asset Bundler Periodic test --- Assets/Engine/SeedAssetList.seed | 492 ++++++++---------- .../bundler_batch_setup_fixture.py | 10 +- .../asset_bundler_batch_tests.py | 30 +- 3 files changed, 235 insertions(+), 297 deletions(-) diff --git a/Assets/Engine/SeedAssetList.seed b/Assets/Engine/SeedAssetList.seed index 45a02f7682..77ec509721 100644 --- a/Assets/Engine/SeedAssetList.seed +++ b/Assets/Engine/SeedAssetList.seed @@ -67,106 +67,98 @@ - + - + - + - + - + - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -264,109 +256,101 @@ - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -387,498 +371,474 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -896,14 +856,6 @@ - - - - - - - - @@ -928,29 +880,13 @@ - - - - - - - - - - - - - - - - - + - + @@ -1451,146 +1387,146 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1699,42 +1635,42 @@ - + - + - + - + - + - + - + - + - + - + diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py index 7a85cb1813..34af4d9115 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py @@ -162,7 +162,7 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) -> else: cmd.append(f"--{key}") if append_defaults: - cmd.append(f"--project={workspace.project}") + cmd.append(f"--project-path={workspace.project}") return cmd # ****** @@ -300,9 +300,9 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) -> workspace.paths.engine_root(), "Code", "Framework", - "AzFramework", - "AzFramework", - "Platform", + "AzCore", + "AzCore", + "PlatformId", "PlatformDefaults.h", ) @@ -318,7 +318,7 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) -> if start_gathering: result = get_platform.match(line) # Try the regex if result: - platform_values[result.group(1).lower()] = counter + platform_values[result.group(1).replace("_ID", "").lower()] = counter counter = counter << 1 elif "(Invalid, -1)" in line: # The line right before the first platform start_gathering = True diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py index 8738e8acdf..1043bbaefa 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py @@ -302,7 +302,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): that generating debug information does not affect asset list creation """ helper = bundler_batch_helper - seed_list = os.path.join(workspace.paths.engine_root(), "Engine", "SeedAssetList.seed") # Engine seed list + seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed") # Engine seed list asset = r"levels\testdependencieslevel\level.pak" # Create Asset list @@ -377,7 +377,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): subcommands. """ helper = bundler_batch_helper - seed_list = os.path.join(workspace.paths.engine_root(), "Engine", "SeedAssetList.seed") # Engine seed list + seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed") # Engine seed list asset = r"levels\testdependencieslevel\level.pak" # Useful bundle locations / names (2 for comparing contents) @@ -465,7 +465,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): "Please rerun with commandline option: '--bundle_platforms=pc,mac'" # fmt:on - seed_list = os.path.join(workspace.paths.engine_root(), "Engine", "SeedAssetList.seed") # Engine seed list + seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed") # Engine seed list # Useful bundle / asset list locations bundle_dir = os.path.dirname(helper["bundle_file"]) @@ -502,13 +502,13 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): for bundle_file in bundle_files.values(): assert os.path.isfile(bundle_file) - # This asset is created on mac platform but not on windows - file_to_check = b"engineassets/shading/defaultprobe_cm.dds.5" # [use byte str because file is in binary] + # This asset is created both on mac and windows platform + file_to_check = b"engineassets/shading/defaultprobe_cm_ibldiffuse.tif.streamingimage" # [use byte str because file is in binary] # Extract the delta catalog file from pc archive. {file_to_check} SHOULD NOT be present for PC file_contents = helper.extract_file_content(bundle_files["pc"], "DeltaCatalog.xml") # fmt:off - assert file_to_check not in file_contents, \ + assert file_to_check in file_contents, \ f"{file_to_check} was found in DeltaCatalog.xml in pc bundle file {bundle_files['pc']}" # fmt:on @@ -619,7 +619,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): # Validate both mac and pc are activated for seed # fmt:off check_seed_platform(helper["seed_list_file"], test_asset, - helper["platform_values"]["pc"] + helper["platform_values"]["osx"]) + helper["platform_values"]["pc"] + helper["platform_values"]["mac"]) # fmt:on # Remove MAC platform @@ -651,7 +651,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): # Validate Mac platform was added back on. Save file contents # fmt:off all_lines = check_seed_platform(helper["seed_list_file"], test_asset, - helper["platform_values"]["pc"] + helper["platform_values"]["osx"]) + helper["platform_values"]["pc"] + helper["platform_values"]["mac"]) # fmt:on # Try to remove platform without specifying a platform to remove (should fail) @@ -1046,7 +1046,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): "--addDefaultSeedListFiles", "--platform=pc", "--print", - f"--project={workspace.project}" + f"--project-path={workspace.project}" ], universal_newlines=True, ) @@ -1115,7 +1115,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): bundle_result_path = os.path.join(bundles_folder, helper.platform_file_name("bundle.pak", workspace.asset_processor_platform)) - bundle_cache_path = os.path.join(workspace.paths.platform_cache(), workspace.project, + bundle_cache_path = os.path.join(workspace.paths.platform_cache(), "Bundles", helper.platform_file_name("bundle.pak", workspace.asset_processor_platform)) @@ -1156,13 +1156,15 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): # fmt:off def test_WindowsAndMac_FilesMarkedSkip_FilesAreSkipped(self, workspace, bundler_batch_helper): expected_assets = [ - "libs/particles/milestone2particles.xml", - "textures/milestone2/particles/fx_sparkstreak_01.dds" + "ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas", + "ui/textures/prefab/button_normal.sprite" ] bundler_batch_helper.call_assetLists( assetListFile=bundler_batch_helper['asset_info_file_request'], - addSeed="libs/particles/milestone2particles.xml", - skip="textures/milestone2/particles/fx_launchermuzzlering_01.dds,textures/milestone2/particles/fx_launchermuzzlefront_01.dds" + addSeed="ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas", + skip="ui/textures/prefab/button_disabled.sprite,ui/scripts/lyshineexamples/animation/multiplesequences.luac," + "ui/textures/prefab/tooltip_sliced.sprite,ui/scripts/lyshineexamples/unloadthiscanvasbutton.luac,fonts/vera.fontfamily,fonts/vera-italic.font," + "fonts/vera.font,fonts/vera-bold.font,fonts/vera-bold-italic.font,fonts/vera-italic.ttf,fonts/vera.ttf,fonts/vera-bold.ttf,fonts/vera-bold-italic.ttf" ) assert os.path.isfile(bundler_batch_helper["asset_info_file_result"]) assets_in_list = [] From eee7bb219ad900643cb4446577e942bc4223f726 Mon Sep 17 00:00:00 2001 From: Vincent Liu <5900509+onecent1101@users.noreply.github.com> Date: Fri, 28 May 2021 10:50:23 -0700 Subject: [PATCH 41/41] [LYN-3996] Update core editor menu (#1030) --- .../Components/Widgets/Menu.qss | 2 +- .../Images/Notifications/link.svg | 4 + .../AzQtComponents/Images/resources.qrc | 1 + .../Private/Editor/AWSCoreEditorManager.h | 2 +- .../Editor/Constants/AWSCoreEditorMenuLinks.h | 53 +++++++++ .../Editor/Constants/AWSCoreEditorMenuNames.h | 44 ++++++++ .../Private/Editor/UI/AWSCoreEditorMenu.h | 14 +-- .../Source/Editor/AWSCoreEditorManager.cpp | 2 +- .../Source/Editor/UI/AWSCoreEditorMenu.cpp | 102 ++++++++++++++---- .../AWSCoreEditorSystemComponentTest.cpp | 4 +- .../Tests/Editor/UI/AWSCoreEditorMenuTest.cpp | 6 +- Gems/AWSCore/Code/awscore_editor_files.cmake | 2 + 12 files changed, 198 insertions(+), 38 deletions(-) create mode 100644 Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/link.svg create mode 100644 Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuLinks.h create mode 100644 Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuNames.h diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Menu.qss b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Menu.qss index af9c675f23..7f48637cc8 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Menu.qss +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Menu.qss @@ -49,7 +49,7 @@ QMenu::right-arrow QMenu::icon { - right: 8px; + right: 20px; } QMenu::indicator:checked diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/link.svg b/Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/link.svg new file mode 100644 index 0000000000..dfd21d157f --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/link.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc b/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc index dbbf0e78e2..7b0c6530ab 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc +++ b/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc @@ -13,5 +13,6 @@ Notifications/checkmark.svg Notifications/download.svg + Notifications/link.svg diff --git a/Gems/AWSCore/Code/Include/Private/Editor/AWSCoreEditorManager.h b/Gems/AWSCore/Code/Include/Private/Editor/AWSCoreEditorManager.h index 721cd6dd6a..98467727ea 100644 --- a/Gems/AWSCore/Code/Include/Private/Editor/AWSCoreEditorManager.h +++ b/Gems/AWSCore/Code/Include/Private/Editor/AWSCoreEditorManager.h @@ -18,7 +18,7 @@ namespace AWSCore class AWSCoreEditorManager { public: - static constexpr const char CLOUD_SERVICES_MENU_TEXT[] = "&Cloud services"; + static constexpr const char AWS_MENU_TEXT[] = "&AWS"; AWSCoreEditorManager(); virtual ~AWSCoreEditorManager(); diff --git a/Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuLinks.h b/Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuLinks.h new file mode 100644 index 0000000000..46acfbd4a3 --- /dev/null +++ b/Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuLinks.h @@ -0,0 +1,53 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#pragma once + +namespace AWSCore +{ + static constexpr const char NewToAWSUrl[] = "https://docs.o3de.org/docs/user-guide/gems/reference/aws/"; + + static constexpr const char AWSAndScriptCanvasUrl[] = "https://docs.o3de.org/docs/user-guide/components/reference/aws/"; + static constexpr const char AWSAndComponentsUrl[] = "https://docs.o3de.org/docs/user-guide/components/reference/aws/"; + static constexpr const char CallAWSResourcesUrl[] = "https://docs.o3de.org/docs/user-guide/components/reference/aws/"; + + static constexpr const char AWSCredentialConfigurationUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-core/configuring-credentials/"; + + static constexpr const char AWSClientAuthGemOverviewUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/"; + static constexpr const char AWSClientAuthCDKAndResourcesUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/"; + static constexpr const char AWSClientAuthScriptCanvasAndLuaUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/"; + static constexpr const char AWSClientAuth3rdPartyAuthProviderUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/"; + static constexpr const char AWSClientAuthCustomAuthProviderUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/"; + static constexpr const char AWSClientAuthPlatformSpecificUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/"; + static constexpr const char AWSClientAuthAPIReferenceUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/"; + + static constexpr const char AWSMetricsGemOverviewUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/"; + static constexpr const char AWSMetricsSetupGemUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/"; + static constexpr const char AWSMetricsScriptingUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/"; + static constexpr const char AWSMetricsAPIReferenceUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/"; + static constexpr const char AWSMetricsAdvancedTopicsUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/"; + static constexpr const char AWSMetricsSettingsUrl[] = + "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/"; +} // namespace AWSCore diff --git a/Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuNames.h b/Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuNames.h new file mode 100644 index 0000000000..a9a8198e52 --- /dev/null +++ b/Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuNames.h @@ -0,0 +1,44 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#pragma once + +namespace AWSCore +{ + static constexpr const char NewToAWSActionText[] = "Getting started with AWS?"; + + static constexpr const char AWSAndO3DEGlobalDocsText[] = "AWS & O3DE global docs"; + static constexpr const char AWSAndScriptCanvasActionText[] = "AWS && ScriptCanvas"; + static constexpr const char AWSAndComponentsActionText[] = "AWS & Components"; + static constexpr const char CallAWSResourcesActionText[] = "Call AWS resources"; + + static constexpr const char AWSCredentialConfigurationActionText[] = "AWS credential configuration"; + + static constexpr const char AWSResourceMappingToolActionText[] = "AWS Resource Mapping Tool..."; + + static constexpr const char AWSClientAuthActionText[] = "Client Auth"; + static constexpr const char AWSClientAuthGemOverviewActionText[] = "Gem Overview"; + static constexpr const char AWSClientAuthCDKAndResourcesActionText[] = "CDK Application and Resource Mappings"; + static constexpr const char AWSClientAuthScriptCanvasAndLuaActionText[] = "Script Canvas and Lua"; + static constexpr const char AWSClientAuth3rdPartyAuthProviderActionText[] = "3rd Party developer Authentication Provider support"; + static constexpr const char AWSClientAuthCustomAuthProviderActionText[] = "Custom developer Authentication Provider support"; + static constexpr const char AWSClientAuthPlatformSpecificActionText[] = "Platform specific Callouts"; + static constexpr const char AWSClientAuthAPIReferenceActionText[] = "API Reference"; + + static constexpr const char AWSMetricsActionText[] = "Metrics"; + static constexpr const char AWSMetricsGemOverviewActionText[] = "Metrics Overview"; + static constexpr const char AWSMetricsSetupGemActionText[] = "Setup Metrics Gem"; + static constexpr const char AWSMetricsScriptingActionText[] = "Scripting with AWS Metrics"; + static constexpr const char AWSMetricsAPIReferenceActionText[] = "C++ API with AWS Metrics Gem"; + static constexpr const char AWSMetricsAdvancedTopicsActionText[] = "Advanced topics"; + static constexpr const char AWSMetricsSettingsActionText[] = "Metrics Settings"; +} // namespace AWSCore diff --git a/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h b/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h index 19f241e368..c892f86b66 100644 --- a/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h +++ b/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h @@ -35,29 +35,23 @@ namespace AWSCore static constexpr const char AWSResourceMappingToolIsRunningText[] = "Resource Mapping Tool is running..."; static constexpr const char AWSResourceMappingToolLogWarningText[] = "Failed to launch Resource Mapping Tool, please check logs for details."; - static constexpr const char AWSResourceMappingToolActionText[] = "AWS Resource Mapping Tool..."; - static constexpr const char CredentialConfigurationActionText[] = "Credential Configuration"; - static constexpr const char CredentialConfigurationUrl[] = "https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/credentials.html"; - static constexpr const char NewToAWSActionText[] = "New to AWS?"; - static constexpr const char NewToAWSUrl[] = "https://o3deorg.netlify.app/docs/user-guide/gems/reference/aws"; - static constexpr const char AWSAndScriptCanvasActionText[] = "AWS && ScriptCanvas"; - static constexpr const char AWSAndScriptCanvasUrl[] = "https://o3deorg.netlify.app/docs/user-guide/gems/reference/aws"; - static constexpr const char AWSClientAuthActionText[] = "Client Auth"; - static constexpr const char AWSMetricsActionText[] = "Metrics"; AWSCoreEditorMenu(const QString& text); ~AWSCoreEditorMenu(); private: + QAction* AddExternalLinkAction(const AZStd::string& name, const AZStd::string& url, const AZStd::string& icon = ""); + void InitializeResourceMappingToolAction(); void InitializeAWSDocActions(); + void InitializeAWSGlobalDocsSubMenu(); void InitializeAWSFeatureGemActions(); // AWSCoreEditorRequestBus interface implementation void SetAWSClientAuthEnabled() override; void SetAWSMetricsEnabled() override; - void SetAWSFeatureActionsEnabled(const AZStd::string actionText); + QMenu* SetAWSFeatureSubMenu(const AZStd::string& menuText); // To improve experience, use process watcher to keep track of ongoing tool process AZStd::unique_ptr m_resourceMappingToolWatcher; diff --git a/Gems/AWSCore/Code/Source/Editor/AWSCoreEditorManager.cpp b/Gems/AWSCore/Code/Source/Editor/AWSCoreEditorManager.cpp index 1e3e44255a..89956d61b8 100644 --- a/Gems/AWSCore/Code/Source/Editor/AWSCoreEditorManager.cpp +++ b/Gems/AWSCore/Code/Source/Editor/AWSCoreEditorManager.cpp @@ -16,7 +16,7 @@ namespace AWSCore { AWSCoreEditorManager::AWSCoreEditorManager() - : m_awsCoreEditorMenu(new AWSCoreEditorMenu(CLOUD_SERVICES_MENU_TEXT)) + : m_awsCoreEditorMenu(new AWSCoreEditorMenu(AWS_MENU_TEXT)) { } diff --git a/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp b/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp index 754cc32751..c319788547 100644 --- a/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp +++ b/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp @@ -13,10 +13,13 @@ #include #include #include +#include #include #include #include +#include +#include #include #include @@ -36,8 +39,8 @@ namespace AWSCore : QMenu(text) , m_resourceMappingToolWatcher(nullptr) { - InitializeResourceMappingToolAction(); InitializeAWSDocActions(); + InitializeResourceMappingToolAction(); this->addSeparator(); InitializeAWSFeatureGemActions(); @@ -58,6 +61,21 @@ namespace AWSCore this->clear(); } + QAction* AWSCoreEditorMenu::AddExternalLinkAction( + const AZStd::string& name, const AZStd::string& url, const AZStd::string& icon) + { + QAction* linkAction = new QAction(QObject::tr(name.c_str())); + QObject::connect(linkAction, &QAction::triggered, this, + [url]() { + QDesktopServices::openUrl(QUrl(url.c_str())); + }); + if (!icon.empty()) + { + linkAction->setIcon(QIcon(icon.c_str())); + } + return linkAction; + } + void AWSCoreEditorMenu::InitializeResourceMappingToolAction() { #ifdef AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED @@ -103,21 +121,21 @@ namespace AWSCore void AWSCoreEditorMenu::InitializeAWSDocActions() { - QAction* credentialConfiguration = new QAction(QObject::tr(CredentialConfigurationActionText)); - QObject::connect(credentialConfiguration, &QAction::triggered, this, []() { - QDesktopServices::openUrl(QUrl(CredentialConfigurationUrl)); - }); - this->addAction(credentialConfiguration); + this->addAction(AddExternalLinkAction(NewToAWSActionText, NewToAWSUrl, ":/Notifications/link.svg")); - QAction* newToAWS = new QAction(QObject::tr(NewToAWSActionText)); - QObject::connect(newToAWS, &QAction::triggered, this, []() { - QDesktopServices::openUrl(QUrl(NewToAWSUrl)); }); - this->addAction(newToAWS); + InitializeAWSGlobalDocsSubMenu(); - QAction* awsAndScriptCanvas = new QAction(QObject::tr(AWSAndScriptCanvasActionText)); - QObject::connect(awsAndScriptCanvas, &QAction::triggered, this, []() { - QDesktopServices::openUrl(QUrl(AWSAndScriptCanvasUrl)); }); - this->addAction(awsAndScriptCanvas); + this->addAction(AddExternalLinkAction( + AWSCredentialConfigurationActionText, AWSCredentialConfigurationUrl, ":/Notifications/link.svg")); + } + + void AWSCoreEditorMenu::InitializeAWSGlobalDocsSubMenu() + { + QMenu* globalDocsMenu = this->addMenu(QObject::tr(AWSAndO3DEGlobalDocsText)); + + globalDocsMenu->addAction(AddExternalLinkAction(AWSAndScriptCanvasActionText, AWSAndScriptCanvasUrl, ":/Notifications/link.svg")); + globalDocsMenu->addAction(AddExternalLinkAction(AWSAndComponentsActionText, AWSAndComponentsUrl, ":/Notifications/link.svg")); + globalDocsMenu->addAction(AddExternalLinkAction(CallAWSResourcesActionText, CallAWSResourcesUrl, ":/Notifications/link.svg")); } void AWSCoreEditorMenu::InitializeAWSFeatureGemActions() @@ -135,25 +153,67 @@ namespace AWSCore void AWSCoreEditorMenu::SetAWSClientAuthEnabled() { - SetAWSFeatureActionsEnabled(AWSClientAuthActionText); + // TODO: instead of creating submenu in core editor, aws feature gem should return submenu component directly + QMenu* subMenu = SetAWSFeatureSubMenu(AWSClientAuthActionText); + + subMenu->addAction(AddExternalLinkAction( + AWSClientAuthGemOverviewActionText, AWSClientAuthGemOverviewUrl, ":/Notifications/link.svg")); + subMenu->addAction(AddExternalLinkAction( + AWSClientAuthCDKAndResourcesActionText, AWSClientAuthCDKAndResourcesUrl, ":/Notifications/link.svg")); + subMenu->addAction(AddExternalLinkAction( + AWSClientAuthScriptCanvasAndLuaActionText, AWSClientAuthScriptCanvasAndLuaUrl, ":/Notifications/link.svg")); + subMenu->addAction(AddExternalLinkAction( + AWSClientAuth3rdPartyAuthProviderActionText, AWSClientAuth3rdPartyAuthProviderUrl, ":/Notifications/link.svg")); + subMenu->addAction(AddExternalLinkAction( + AWSClientAuthCustomAuthProviderActionText, AWSClientAuthCustomAuthProviderUrl, ":/Notifications/link.svg")); + subMenu->addAction(AddExternalLinkAction( + AWSClientAuthPlatformSpecificActionText, AWSClientAuthPlatformSpecificUrl, ":/Notifications/link.svg")); + subMenu->addAction(AddExternalLinkAction( + AWSClientAuthAPIReferenceActionText, AWSClientAuthAPIReferenceUrl, ":/Notifications/link.svg")); } void AWSCoreEditorMenu::SetAWSMetricsEnabled() { - SetAWSFeatureActionsEnabled(AWSMetricsActionText); + // TODO: instead of creating submenu in core editor, aws feature gem should return submenu component directly + QMenu* subMenu = SetAWSFeatureSubMenu(AWSMetricsActionText); + + subMenu->addAction(AddExternalLinkAction( + AWSMetricsGemOverviewActionText, AWSMetricsGemOverviewUrl, ":/Notifications/link.svg")); + subMenu->addAction(AddExternalLinkAction( + AWSMetricsSetupGemActionText, AWSMetricsSetupGemUrl, ":/Notifications/link.svg")); + subMenu->addAction(AddExternalLinkAction( + AWSMetricsScriptingActionText, AWSMetricsScriptingUrl, ":/Notifications/link.svg")); + subMenu->addAction(AddExternalLinkAction( + AWSMetricsAPIReferenceActionText, AWSMetricsAPIReferenceUrl, ":/Notifications/link.svg")); + subMenu->addAction(AddExternalLinkAction( + AWSMetricsAdvancedTopicsActionText, AWSMetricsAdvancedTopicsUrl, ":/Notifications/link.svg")); + + AZStd::string priorAlias = AZ::IO::FileIOBase::GetInstance()->GetAlias("@devroot@"); + AZStd::string configFilePath = priorAlias + "\\Gems\\AWSMetrics\\Code\\" + AZ::SettingsRegistryInterface::RegistryFolder; + AzFramework::StringFunc::Path::Normalize(configFilePath); + + QAction* settingsAction = new QAction(QObject::tr(AWSMetricsSettingsActionText)); + QObject::connect(settingsAction, &QAction::triggered, this, + [configFilePath](){ + QDesktopServices::openUrl(QUrl::fromLocalFile(configFilePath.c_str())); + }); + subMenu->addAction(settingsAction); } - void AWSCoreEditorMenu::SetAWSFeatureActionsEnabled(const AZStd::string actionText) + QMenu* AWSCoreEditorMenu::SetAWSFeatureSubMenu(const AZStd::string& menuText) { auto actionList = this->actions(); for (QList::iterator itr = actionList.begin(); itr != actionList.end(); itr++) { - if (QString::compare((*itr)->text(), actionText.c_str()) == 0) + if (QString::compare((*itr)->text(), menuText.c_str()) == 0) { - (*itr)->setIcon(QIcon(QString(":/Notifications/checkmark.svg"))); - (*itr)->setEnabled(true); - break; + QMenu* subMenu = new QMenu(QObject::tr(menuText.c_str())); + subMenu->setIcon(QIcon(QString(":/Notifications/checkmark.svg"))); + this->insertMenu(*itr, subMenu); + this->removeAction(*itr); + return subMenu; } } + return nullptr; } } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Tests/AWSCoreEditorSystemComponentTest.cpp b/Gems/AWSCore/Code/Tests/AWSCoreEditorSystemComponentTest.cpp index e9c249f1c8..ff78d8e252 100644 --- a/Gems/AWSCore/Code/Tests/AWSCoreEditorSystemComponentTest.cpp +++ b/Gems/AWSCore/Code/Tests/AWSCoreEditorSystemComponentTest.cpp @@ -85,7 +85,7 @@ TEST_F(AWSCoreEditorSystemComponentTest, NotifyMainWindowInitialized_HaveDummyMe testMenuBar->addMenu("dummy menu"); AzToolsFramework::EditorEvents::Bus::Broadcast(&AzToolsFramework::EditorEvents::NotifyMainWindowInitialized, &testMainWindow); EXPECT_TRUE(testMenuBar->actions().size() == 2); - EXPECT_TRUE(QString::compare(testMenuBar->actions()[1]->text(), AWSCoreEditorManager::CLOUD_SERVICES_MENU_TEXT) == 0); + EXPECT_TRUE(QString::compare(testMenuBar->actions()[1]->text(), AWSCoreEditorManager::AWS_MENU_TEXT) == 0); } TEST_F(AWSCoreEditorSystemComponentTest, NotifyMainWindowInitialized_HaveHelpMenuInMenuBar_ExpectedMenuGetsAddedAtFront) @@ -95,5 +95,5 @@ TEST_F(AWSCoreEditorSystemComponentTest, NotifyMainWindowInitialized_HaveHelpMen testMenuBar->addMenu(AWSCoreEditorSystemComponent::EDITOR_HELP_MENU_TEXT); AzToolsFramework::EditorEvents::Bus::Broadcast(&AzToolsFramework::EditorEvents::NotifyMainWindowInitialized, &testMainWindow); EXPECT_TRUE(testMenuBar->actions().size() == 2); - EXPECT_TRUE(QString::compare(testMenuBar->actions()[0]->text(), AWSCoreEditorManager::CLOUD_SERVICES_MENU_TEXT) == 0); + EXPECT_TRUE(QString::compare(testMenuBar->actions()[0]->text(), AWSCoreEditorManager::AWS_MENU_TEXT) == 0); } diff --git a/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreEditorMenuTest.cpp b/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreEditorMenuTest.cpp index 7a578d2bbe..bde2a43993 100644 --- a/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreEditorMenuTest.cpp +++ b/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreEditorMenuTest.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -35,6 +36,7 @@ class AWSCoreEditorMenuTest { AWSCoreEditorUIFixture::SetUp(); AWSCoreFixture::SetUp(); + m_localFileIO->SetAlias("@devroot@", "dummy engine root"); } void TearDown() override @@ -77,12 +79,12 @@ TEST_F(AWSCoreEditorMenuTest, AWSCoreEditorMenu_BroadcastFeatureGemsAreEnabled_C QList actualActions = testMenu.actions(); for (QList::iterator itr = actualActions.begin(); itr != actualActions.end(); itr++) { - if (QString::compare((*itr)->text(), AWSCoreEditorMenu::AWSClientAuthActionText) == 0) + if (QString::compare((*itr)->text(), AWSClientAuthActionText) == 0) { EXPECT_TRUE((*itr)->isEnabled()); } - if (QString::compare((*itr)->text(), AWSCoreEditorMenu::AWSMetricsActionText) == 0) + if (QString::compare((*itr)->text(), AWSMetricsActionText) == 0) { EXPECT_TRUE((*itr)->isEnabled()); } diff --git a/Gems/AWSCore/Code/awscore_editor_files.cmake b/Gems/AWSCore/Code/awscore_editor_files.cmake index 652f0455e1..13bfbb6102 100644 --- a/Gems/AWSCore/Code/awscore_editor_files.cmake +++ b/Gems/AWSCore/Code/awscore_editor_files.cmake @@ -12,6 +12,8 @@ set(FILES Include/Private/AWSCoreEditorSystemComponent.h Include/Private/Editor/AWSCoreEditorManager.h + Include/Private/Editor/Constants/AWSCoreEditorMenuLinks.h + Include/Private/Editor/Constants/AWSCoreEditorMenuNames.h Include/Private/Editor/UI/AWSCoreEditorMenu.h Include/Private/Editor/UI/AWSCoreResourceMappingToolAction.h Source/AWSCoreEditorSystemComponent.cpp